From: Kevin Day Date: Mon, 22 Aug 2022 23:11:19 +0000 (-0500) Subject: Progress: Continue program related work. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=410855834eeeab23b2b347617945f3e67330882f;p=fll Progress: Continue program related work. The pointer is a double pointer in the memory function and as such the NULL check should be performed in f_memory. Add print source and header files to all programs. Stub out the necessary changes regarding the new setting data type in all programs. Move file stream functions into their own files. Add missing file stream lock and unlock functions. Add F_okay and F_okay_not status codes. Get utf8, status_code, and fss_status_code working with new program design (including the new settings data type). --- diff --git a/build/level_0/settings b/build/level_0/settings index fd4c97f..4315075 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -28,7 +28,7 @@ build_sources_library conversion.c private-conversion.c conversion/common.c build_sources_library directory.c directory/common.c private-directory.c build_sources_library environment.c build_sources_library execute.c -build_sources_library file.c private-file.c file/common.c +build_sources_library file.c private-file.c file/common.c file/stream.c build_sources_library fss.c private-fss.c fss/common.c fss/named.c fss/nest.c fss/set.c build_sources_library iki.c iki/common.c iki/data.c private-iki.c iki/private-data.c build_sources_library limit.c limit/set.c limit/value.c limit/private-set.c limit/private-value.c @@ -57,7 +57,7 @@ build_sources_headers conversion.h conversion/common.h build_sources_headers directory.h directory/common.h directory/type.h build_sources_headers environment.h environment/common.h build_sources_headers execute.h execute/common.h -build_sources_headers file.h file/common.h +build_sources_headers file.h file/common.h file/stream.h build_sources_headers fss.h fss/comment.h fss/common.h fss/delimit.h fss/named.h fss/nest.h fss/quote.h fss/set.h build_sources_headers iki.h iki/common.h iki/data.h build_sources_headers limit.h limit/set.h limit/value.h diff --git a/build/level_2/settings b/build/level_2/settings index 6d66025..39869bc 100644 --- a/build/level_2/settings +++ b/build/level_2/settings @@ -30,7 +30,7 @@ build_sources_library fss_status_string.c build_sources_library iki.c private-iki.c build_sources_library path.c build_sources_library print.c -build_sources_library program.c program/common.c private-program.c +build_sources_library program.c program/common.c program/print.c private-program.c build_sources_library status_string.c build_sources_headers control_group.h @@ -42,7 +42,7 @@ build_sources_headers fss_status_string.h build_sources_headers iki.h build_sources_headers path.h build_sources_headers print.h -build_sources_headers program.h program/common.h +build_sources_headers program.h program/common.h program/print.h build_sources_headers status_string.h build_script yes diff --git a/build/monolithic/settings b/build/monolithic/settings index 1c032a8..d2142d2 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -28,7 +28,7 @@ build_sources_library level_0/conversion.c level_0/private-conversion.c level_0/ build_sources_library level_0/directory.c level_0/directory/common.c level_0/private-directory.c build_sources_library level_0/environment.c build_sources_library level_0/execute.c -build_sources_library level_0/file.c level_0/private-file.c level_0/file/common.c +build_sources_library level_0/file.c level_0/private-file.c level_0/file/common.c level_0/file/stream.c build_sources_library level_0/fss.c level_0/private-fss.c level_0/fss/common.c level_0/fss/named.c level_0/fss/nest.c level_0/fss/set.c build_sources_library level_0/iki.c level_0/iki/common.c level_0/iki/data.c level_0/private-iki.c level_0/iki/private-data.c build_sources_library level_0/limit.c level_0/limit/set.c level_0/limit/value.c level_0/limit/private-set.c level_0/limit/private-value.c @@ -67,7 +67,7 @@ build_sources_library level_2/fss_status_string.c build_sources_library level_2/iki.c level_2/private-iki.c build_sources_library level_2/path.c build_sources_library level_2/print.c -build_sources_library level_2/program.c level_2/program/common.c level_2/private-program.c +build_sources_library level_2/program.c level_2/program/common.c level_2/program/print.c level_2/private-program.c build_sources_library level_2/status_string.c build_sources_library-monolithic level_0/thread.c level_0/private-thread.c level_0/thread/attribute.c level_0/thread/barrier.c level_0/thread/barrier_attribute.c level_0/thread/condition.c level_0/thread/condition_attribute.c level_0/thread/id.c level_0/thread/key.c level_0/thread/lock.c level_0/thread/lock_attribute.c level_0/thread/mutex.c level_0/thread/mutex_attribute.c level_0/thread/once.c level_0/thread/semaphore.c level_0/thread/set.c level_0/thread/spin.c @@ -81,7 +81,7 @@ build_sources_headers level_0/conversion.h level_0/conversion/common.h build_sources_headers level_0/directory.h level_0/directory/common.h level_0/directory/type.h build_sources_headers level_0/environment.h level_0/environment/common.h build_sources_headers level_0/execute.h level_0/execute/common.h -build_sources_headers level_0/file.h level_0/file/common.h +build_sources_headers level_0/file.h level_0/file/common.h level_0/file/stream.h build_sources_headers level_0/fss.h level_0/fss/comment.h level_0/fss/common.h level_0/fss/delimit.h level_0/fss/named.h level_0/fss/nest.h level_0/fss/quote.h level_0/fss/set.h build_sources_headers level_0/iki.h level_0/iki/common.h level_0/iki/data.h build_sources_headers level_0/limit.h level_0/limit/set.h level_0/limit/value.h @@ -122,7 +122,7 @@ build_sources_headers level_2/fss_status_string.h build_sources_headers level_2/iki.h build_sources_headers level_2/path.h build_sources_headers level_2/print.h -build_sources_headers level_2/program.h level_2/program/common.h +build_sources_headers level_2/program.h level_2/program/common.h level_2/program/print.h build_sources_headers level_2/status_string.h build_sources_headers-monolithic level_0/thread.h level_0/thread/attribute.h level_0/thread/barrier.h level_0/thread/barrier_attribute.h level_0/thread/condition.h level_0/thread/condition_attribute.h level_0/thread/id.h level_0/thread/key.h level_0/thread/lock.h level_0/thread/lock_attribute.h level_0/thread/mutex.h level_0/thread/mutex_attribute.h level_0/thread/once.h level_0/thread/semaphore.h level_0/thread/set.h level_0/thread/spin.h diff --git a/level_0/f_file/c/file.c b/level_0/f_file/c/file.c index c176669..e842f15 100644 --- a/level_0/f_file/c/file.c +++ b/level_0/f_file/c/file.c @@ -1915,520 +1915,6 @@ extern "C" { } #endif // _di_f_file_stat_by_id_ -#ifndef _di_f_file_stream_close_ - f_status_t f_file_stream_close(f_file_t * const file) { - #ifndef _di_level_0_parameter_checking_ - if (!file) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (!file->stream) return F_stream_not; - - if (fclose(file->stream) == EOF) { - - // According to man pages, further access to a stream on error results in undefined behavior. - file->stream = 0; - - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); - if (errno == EBADF) return F_status_set_error(F_file_descriptor); - if (errno == EFBIG) return F_status_set_error(F_file_overflow); - if (errno == EDEADLK) return F_status_set_error(F_deadlock); - if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); - if (errno == EDQUOT) return F_status_set_error(F_space_not); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == EIO) return F_status_set_error(F_input_output); - if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); - if (errno == ENOLCK) return F_status_set_error(F_lock); - if (errno == ENOSPC) return F_status_set_error(F_space_not); - if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); - if (errno == EPERM) return F_status_set_error(F_prohibited); - if (errno == EPIPE) return F_status_set_error(F_pipe_not); - - return F_status_set_error(F_file_close); - } - - file->stream = 0; - - return F_none; - } -#endif // _di_f_file_stream_close_ - -#ifndef _di_f_file_stream_flush_ - f_status_t f_file_stream_flush(const f_file_t file) { - - if (!file.stream) return F_stream_not; - - // Only 0 is considered a success and so any non-zero value could be an error. - if (fflush(file.stream) != 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); - if (errno == EBADF) return F_status_set_error(F_file_descriptor); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == EIO) return F_status_set_error(F_input_output); - if (errno == EISDIR) return F_status_set_error(F_file_type_directory); - - return F_status_set_error(F_file_synchronize); - } - - return F_none; - } -#endif // _di_f_file_stream_flush_ - -#ifndef _di_f_file_stream_open_ - f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file) { - #ifndef _di_level_0_parameter_checking_ - if (!file) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (!path.used) return F_data_not; - - if (mode.used) { - file->stream = fopen(path.string, mode.string); - } - else { - file->stream = fopen(path.string, private_f_file_stream_open_mode_determine(file->flag)); - } - - if (!file->stream) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block); - if (errno == EEXIST) return F_status_set_error(F_file_found); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == EFBIG || errno == EOVERFLOW) return F_status_set_error(F_number_overflow); - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == ELOOP) return F_status_set_error(F_loop); - if (errno == ENFILE) return F_status_set_error(F_file_open_max); - if (errno == ENOENT) return F_status_set_error(F_file_found_not); - if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); - if (errno == ENOMEM) return F_status_set_error(F_memory_not); - if (errno == ENOSPC) return F_status_set_error(F_space_not); - if (errno == EPERM) return F_status_set_error(F_prohibited); - if (errno == EROFS) return F_status_set_error(F_read_only); - if (errno == ETXTBSY) return F_status_set_error(F_busy); - if (errno == EISDIR) return F_status_set_error(F_directory); - if (errno == EOPNOTSUPP) return F_status_set_error(F_supported_not); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // _di_f_file_stream_open_ - -#ifndef _di_f_file_stream_open_descriptor_ - f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file) { - #ifndef _di_level_0_parameter_checking_ - if (!file) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (file->id == -1) return F_file_descriptor_not; - - if (mode.used) { - file->stream = fdopen(file->id, private_f_file_stream_open_mode_determine(file->flag)); - } - else { - file->stream = fdopen(file->id, mode.string); - } - - if (!file->stream) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); - if (errno == EBADF) return F_status_set_error(F_file_descriptor); - if (errno == EFBIG) return F_status_set_error(F_file_overflow); - if (errno == EDEADLK) return F_status_set_error(F_deadlock); - if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); - if (errno == EDQUOT) return F_status_set_error(F_space_not); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == EIO) return F_status_set_error(F_input_output); - if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); - if (errno == ENODEV) return F_status_set_error(F_device_not); - if (errno == ENOLCK) return F_status_set_error(F_lock); - if (errno == ENOMEM) return F_status_set_error(F_memory_not); - if (errno == ENOSPC) return F_status_set_error(F_space_not); - if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); - if (errno == EPERM) return F_status_set_error(F_prohibited); - if (errno == EPIPE) return F_status_set_error(F_pipe_not); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // _di_f_file_stream_open_descriptor_ - -#ifndef _di_f_file_stream_read_ - f_status_t f_file_stream_read(const f_file_t file, f_string_dynamic_t * const buffer) { - #ifndef _di_level_0_parameter_checking_ - if (!file.size_read) return F_status_set_error(F_parameter); - if (!buffer) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (!file.stream) return F_stream_not; - - flockfile(file.stream); - - if (feof_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_none_eof; - } - - if (ferror_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_status_set_error(F_error); - } - - f_status_t status = F_none; - size_t size_read = 0; - - do { - status = f_string_dynamic_increase_by(file.size_read, buffer); - - if (F_status_is_error(status)) { - funlockfile(file.stream); - - return status; - } - - size_read = fread_unlocked(buffer->string + buffer->used, sizeof(f_char_t), file.size_read, file.stream); - - if (ferror_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_status_set_error(F_file_read); - } - - buffer->used += size_read; - - } while (size_read == file.size_read && !feof_unlocked(file.stream)); - - funlockfile(file.stream); - - return F_none_eof; - } -#endif // _di_f_file_stream_read_ - -#ifndef _di_f_file_stream_read_block_ - f_status_t f_file_stream_read_block(const f_file_t file, f_string_dynamic_t * const buffer) { - #ifndef _di_level_0_parameter_checking_ - if (!file.size_read) return F_status_set_error(F_parameter); - if (!buffer) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (!file.stream) return F_stream_not; - - flockfile(file.stream); - - if (feof_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_none_eof; - } - - if (ferror_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_status_set_error(F_error); - } - - { - const f_status_t status = f_string_dynamic_increase_by(file.size_read, buffer); - - if (F_status_is_error(status)) { - funlockfile(file.stream); - - return status; - } - } - - const size_t size_read = fread_unlocked(buffer->string + buffer->used, sizeof(f_char_t), file.size_read, file.stream); - - if (ferror_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_status_set_error(F_file_read); - } - - if (size_read) { - buffer->used += size_read; - } - - if (feof_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_none_eof; - } - - funlockfile(file.stream); - - return F_none; - } -#endif // _di_f_file_stream_read_block_ - -#ifndef _di_f_file_stream_read_until_ - f_status_t f_file_stream_read_until(const f_file_t file, const f_array_length_t total, f_string_dynamic_t * const buffer) { - #ifndef _di_level_0_parameter_checking_ - if (!file.size_read) return F_status_set_error(F_parameter); - if (!buffer) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (!file.stream) return F_stream_not; - if (!total) return F_data_not; - - flockfile(file.stream); - - if (feof_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_none_eof; - } - - if (ferror_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_status_set_error(F_error); - } - - { - const f_status_t status = f_string_dynamic_increase_by(total, buffer); - - if (F_status_is_error(status)) { - funlockfile(file.stream); - - return F_none_eof; - } - } - - f_array_length_t buffer_size = file.size_read; - f_array_length_t buffer_count = 0; - - size_t size_read = 0; - - for (;;) { - - if (buffer_count + buffer_size > total) { - buffer_size = total - buffer_count; - } - - size_read = fread_unlocked(buffer->string + buffer->used, sizeof(f_char_t), buffer_size, file.stream); - - if (ferror_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_status_set_error(F_file_read); - } - - buffer->used += size_read; - - if (feof_unlocked(file.stream)) { - funlockfile(file.stream); - - return F_none_eof; - } - - buffer_count += size_read; - - if (buffer_count >= total) break; - } // for - - funlockfile(file.stream); - - return F_none_stop; - } -#endif // _di_f_file_stream_read_until_ - -#ifndef _di_f_file_stream_reopen_ - f_status_t f_file_stream_reopen(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file) { - #ifndef _di_level_0_parameter_checking_ - if (!file) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (!path.used && !mode.used) return F_data_not; - - FILE *result = 0; - - if (mode.used) { - result = freopen(path.used ? path.string : 0, mode.string, file->stream); - } - else { - result = freopen(path.used ? path.string : 0, private_f_file_stream_open_mode_determine(file->flag), file->stream); - } - - if (!result) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); - if (errno == EBADF) return F_status_set_error(F_file_descriptor); - if (errno == EFBIG) return F_status_set_error(F_file_overflow); - if (errno == EDEADLK) return F_status_set_error(F_deadlock); - if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); - if (errno == EDQUOT) return F_status_set_error(F_space_not); - if (errno == EFAULT) return F_status_set_error(F_buffer); - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == EIO) return F_status_set_error(F_input_output); - if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); - if (errno == ENOLCK) return F_status_set_error(F_lock); - if (errno == ENOSPC) return F_status_set_error(F_space_not); - if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); - if (errno == EPERM) return F_status_set_error(F_prohibited); - if (errno == EPIPE) return F_status_set_error(F_pipe_not); - - return F_status_set_error(F_failure); - } - - file->stream = result; - - return F_none; - } -#endif // _di_f_file_stream_reopen_ - -#ifndef _di_f_file_stream_write_ - f_status_t f_file_stream_write(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written) { - - if (!file.stream || !buffer.used || !file.size_write) { - if (written) { - *written = 0; - } - - return file.stream ? F_data_not : F_stream_not; - } - - if (written) { - const f_status_t status = private_f_file_stream_write_until(file, buffer, buffer.used, written); - - if (status == F_none && *written == buffer.used) return F_none_eos; - } - else { - f_array_length_t written_local = 0; - - const f_status_t status = private_f_file_stream_write_until(file, buffer, buffer.used, &written_local); - - if (status == F_none && written_local == buffer.used) return F_none_eos; - } - - return F_none; - } -#endif // _di_f_file_stream_write_ - -#ifndef _di_f_file_stream_write_block_ - f_status_t f_file_stream_write_block(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written) { - - if (!file.stream || !buffer.used || !file.size_write) { - if (written) { - *written = 0; - } - - return file.stream ? F_data_not : F_stream_not; - } - - const f_array_length_t write_max = file.size_write > buffer.used ? buffer.used : file.size_write; - - if (written) { - const f_status_t status = private_f_file_stream_write_until(file, buffer, write_max, written); - - if (status == F_none) { - if (*written == buffer.used) return F_none_eos; - if (*written == write_max) return F_none_stop; - } - } - else { - f_array_length_t written_local = 0; - - const f_status_t status = private_f_file_stream_write_until(file, buffer, write_max, &written_local); - - if (status == F_none) { - if (written_local == buffer.used) return F_none_eos; - if (written_local == write_max) return F_none_stop; - } - } - - return F_none; - } -#endif // _di_f_file_stream_write_block_ - -#ifndef _di_f_file_stream_write_until_ - f_status_t f_file_stream_write_until(const f_file_t file, const f_string_static_t buffer, const f_array_length_t total, f_array_length_t * const written) { - - if (!file.stream || !buffer.used || !total || !file.size_write) { - if (written) { - *written = 0; - } - - return file.stream ? F_data_not : F_stream_not; - } - - const f_array_length_t write_max = total > buffer.used ? buffer.used : total; - - if (written) { - const f_status_t status = private_f_file_stream_write_until(file, buffer, write_max, written); - - if (status == F_none) { - if (*written == buffer.used) return F_none_eos; - if (*written == write_max) return F_none_stop; - } - } - else { - f_array_length_t written_local = 0; - - const f_status_t status = private_f_file_stream_write_until(file, buffer, buffer.used, &written_local); - - if (status == F_none) { - if (written_local == buffer.used) return F_none_eos; - if (written_local == write_max) return F_none_stop; - } - } - - return F_none; - } -#endif // _di_f_file_stream_write_until_ - -#ifndef _di_f_file_stream_write_range_ - f_status_t f_file_stream_write_range(const f_file_t file, const f_string_static_t buffer, const f_string_range_t range, f_array_length_t * const written) { - - if (!file.stream || !buffer.used || range.start > range.stop || range.start >= buffer.used || !file.size_write) { - if (written) { - *written = 0; - } - - return file.stream ? F_data_not : F_stream_not; - } - - const f_array_length_t write_max = (range.stop - range.start) + 1 > buffer.used ? buffer.used : (range.stop - range.start) + 1; - - if (written) { - const f_string_static_t buffer_adjusted = macro_f_string_static_t_initialize(buffer.string + range.start, 0, buffer.used - range.start); - - const f_status_t status = private_f_file_stream_write_until(file, buffer_adjusted, write_max, written); - - if (status == F_none) { - if (range.start + *written == buffer.used) return F_none_eos; - if (range.start + *written == write_max) return F_none_stop; - } - } - else { - const f_string_static_t buffer_adjusted = macro_f_string_static_t_initialize(buffer.string + range.start, 0, buffer.used - range.start); - f_array_length_t written_local = 0; - - const f_status_t status = private_f_file_stream_write_until(file, buffer_adjusted, write_max, &written_local); - - if (status == F_none) { - if (range.start + written_local == buffer.used) return F_none_eos; - if (range.start + written_local == write_max) return F_none_stop; - } - } - - return F_none; - } -#endif // _di_f_file_stream_write_range_ - #ifndef _di_f_file_touch_ f_status_t f_file_touch(const f_string_static_t path, const mode_t mode, const bool dereference) { diff --git a/level_0/f_file/c/file.h b/level_0/f_file/c/file.h index 949ccf6..37c9850 100644 --- a/level_0/f_file/c/file.h +++ b/level_0/f_file/c/file.h @@ -7,10 +7,6 @@ * * Provides structures and data types for a file I/O. * Provides operations for opening/closing files. - * - * @fixme Currently this uses makedev(3) to create devices, which is non-standard. - * The documentation for mknod(2) isn't clear on how to make major/minor based block and character devices. - * Find out how to implement this and elliminate the use of the non-standard makedev(3) call. */ #ifndef _F_file_h #define _F_file_h @@ -39,6 +35,7 @@ // FLL-0 file includes. #include +#include #ifdef __cplusplus extern "C" { @@ -2052,459 +2049,6 @@ extern "C" { #endif // _di_f_file_stat_by_id_ /** - * Close an open file stream. - * - * @param file - * The file information. - * The file.stream is set to NULL, on both success or on failure. - * - * @return - * F_none on success. - * F_stream_not if file.stream is NULL. - * - * F_access_denied (with error bit) on access denied. - * F_block (with error bit) if the action would block and non-blocking is set on the stream. - * F_buffer (with error bit) if the buffer is invalid. - * F_deadlock (with error bit) if operation would cause a deadlock. - * F_file_descriptor (with error bit) if file descriptor is invalid. - * F_file_descriptor_max (with error bit) if max file descriptors is reached. - * F_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size. - * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. - * F_input_output (with error bit) on I/O error. - * F_interrupt (with error bit) when program received an interrupt signal, halting operation. - * F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments. - * F_parameter (with error bit) if a parameter is invalid. - * F_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed. - * F_space_not (with error bit) if file system is out of space (or file system quota is reached). - * F_socket_not (with error bit) if the datagram socket in which a peer has not been set (for socket related streams). - * - * F_file_close (with error bit) on any other error. - * - * @see fclose() - */ -#ifndef _di_f_file_stream_close_ - extern f_status_t f_file_stream_close(f_file_t * const file); -#endif // _di_f_file_stream_close_ - -/** - * Flush a file stream. - * - * @param file - * The file information. - * The file.id is updated with the file descriptor, if necessary and able. - * - * @return - * F_none is returned on success. - * F_stream_not if file.stream is NULL. - * F_file_descriptor_not if file.id is -1. - * - * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. - * F_buffer (with error bit) if the buffer is invalid. - * F_file_closed (with error bit) if file is not open. - * F_file_descriptor (with error bit) if the file descriptor is invalid. - * F_file_type_directory (with error bit) if file descriptor represents a directory. - * F_input_output (with error bit) on I/O error. - * F_interrupt (with error bit) if interrupt was received. - * - * F_file_synchronize (with error bit) on any other error. - * - * @see fflush() - */ -#ifndef _di_f_file_stream_flush_ - extern f_status_t f_file_stream_flush(const f_file_t file); -#endif // _di_f_file_stream_flush_ - -/** - * Open a file stream. - * - * The file descriptor is retrieved on success, if necessary and able. - * - * If the file stream is open, it is closed before re-opening. - * - * This is often used for changing the file pointed to by standard streams such as stdout. - * - * @param path - * The file path. - * @param mode - * The file modes do use when opening, as an fopen() file mode string. - * Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe). - * If neither truncate nor append are specified in write only mode, then the failsafe is to append. - * - * File Modes (fopen() file modes vs open file modes): - * - "r": O_RDONLY. - * - "w": O_WRONLY | O_CREAT | O_TRUNC. - * - "a": O_WRONLY | O_CREAT | O_APPEND. - * - "r+": O_RDWR. - * - "w+": O_RDWR | O_CREAT | O_TRUNC. - * - "a+": O_RDWR | O_CREAT | O_APPEND. - * @param file - * The file information. - * The file.stream is updated if necessary. - * The file.id is updated with the file descriptor, if necessary and able. - * - * @return - * F_none is returned on success. - * F_data_not if both path.used is 0. - * - * F_access_denied (with error bit) on access denied. - * F_buffer (with error bit) if the buffer is invalid. - * F_busy (with error bit) if file system is too busy to perform write. - * F_file_descriptor (with error bit) if unable to load the file descriptor. - * F_file_found_not (with error bit) if the file was not found. - * F_file_open_max (with error bit) when system-wide max open files is reached. - * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. - * F_filesystem_quota_block (with error bit) if file system's disk blocks or inodes are exhausted. - * F_interrupt (with error bit) when program received an interrupt signal, halting operation. - * F_loop (with error bit) on loop error. - * F_memory_not (with error bit) if out of memory. - * F_name (with error bit) on path name is too long. - * F_number_overflow (with error bit) on overflow error. - * F_parameter (with error bit) if a parameter is invalid. - * F_prohibited (with error bit) if file system does not allow for making changes. - * F_read_only (with error bit) if file is read-only. - * F_supported_not (with error bit) fo unsupported file types. - * F_failure (with error bit) for any other error. - * - * @see fopen() - */ -#ifndef _di_f_file_stream_open_ - extern f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file); -#endif // _di_f_file_stream_open_ - -/** - * Open a file stream from a file descriptor. - * - * @param mode - * The file modes do use when opening. - * Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe). - * If neither truncate nor append are not specified in write only mode, then the failsafe is to append. - * This should match the modes used to open the file descriptor as it relates to the stream modes. - * @param file - * The file with a valid file descriptor (file.id). - * - * @return - * F_none is returned on success. - * F_file_descriptor_not if file.id is -1. - * - * F_access_denied (with error bit) on access denied. - * F_block (with error bit) if the action would block and non-blocking is set on the stream. - * F_buffer (with error bit) if the buffer is invalid. - * F_deadlock (with error bit) if operation would cause a deadlock. - * F_file_descriptor (with error bit) if file descriptor is invalid. - * F_file_descriptor_max (with error bit) if max file descriptors is reached. - * F_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size. - * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. - * F_interrupt (with error bit) when program received an interrupt signal, halting operation. - * F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments. - * F_parameter (with error bit) if a parameter is invalid. - * F_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed. - * F_prohibited (with error bit) if file system does not allow for making changes. - * F_socket_not (with error bit) if socket is not connected. - * F_space_not (with error bit) if the file system is out of space (or file system quota is reached). - * - * @see fdopen() - */ -#ifndef _di_f_file_stream_open_descriptor_ - extern f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file); -#endif // _di_f_file_stream_open_descriptor_ - -/** - * Read until EOF is reached. - * - * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. - * - * @param file - * The file to read. - * The file.size_read represents the amount to process at a given time. - * @param buffer - * The buffer the file is being read into. - * The contents of the file is appended into this buffer. - * - * @return - * F_none_eof on success and EOF was reached. - * F_stream_not if file.stream is NULL. - * - * F_block (with error bit) if file descriptor is set to non-block and the read would result in a blocking operation. - * F_buffer (with error bit) if the buffer is invalid. - * F_error (with error bit) if the file is already in the error state at the start of this function. - * F_file_closed (with error bit) if file is not open. - * F_file_descriptor (with error bit) if the file descriptor is invalid. - * F_file_type_directory (with error bit) if file descriptor represents a directory. - * F_input_output (with error bit) on I/O error. - * F_interrupt (with error bit) if interrupt was received. - * F_parameter (with error bit) if a parameter is invalid. - * - * @see flockfile() - * @see feof_unlocked() - * @see ferror_unlocked() - * @see fread_unlocked() - * @see funlockfile() - */ -#ifndef _di_f_file_stream_read_ - extern f_status_t f_file_stream_read(const f_file_t file, f_string_dynamic_t * const buffer); -#endif // _di_f_file_stream_read_ - -/** - * Read until a single block is filled or EOF is reached. - * - * To determine how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. - * - * @param file - * The file to read. - * The file.size_read represents the amount to process at a given time. - * @param buffer - * The buffer the file is being read into. - * The contents of the file is appended into this buffer. - * - * @return - * F_none on success. - * F_none_eof on success and EOF was reached. - * F_stream_not if file.stream is NULL. - * - * F_error (with error bit) if the file is already in the error state at the start of this function. - * F_file_closed (with error bit) if the file is closed. - * F_file_read (with error bit) on file read error. - * F_parameter (with error bit) if a parameter is invalid. - * - * @see feof_unlocked() - * @see ferror_unlocked() - * @see flockfile() - * @see fread() - * @see funlockfile() - */ -#ifndef _di_f_file_stream_read_block_ - extern f_status_t f_file_stream_read_block(const f_file_t file, f_string_dynamic_t * const buffer); -#endif // _di_f_file_stream_read_block_ - -/** - * Read until a given number or EOF is reached, storing it in the buffer. - * - * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. - * - * This is different from simply using the file.size_read. - * The file.size_read represents the amount to process at a given time. - * The total represents the maximum number of file.size_read to process. - * For example, if file.size_read is 16 and total is 128, then this function would need to be called 8 times until total is reached. - * - * @param file - * The file to read. - * The file.size_read represents the amount to process at a given time. - * @param total - * The total bytes to read, unless EOF is reached first. - * @param buffer - * The buffer the file is being read into. - * - * @return - * F_none_eof on success and EOF was reached. - * F_none_stop on success and total was reached. - * F_data_not if total is 0. - * F_stream_not if file.stream is NULL. - * - * F_error (with error bit) if the file is already in the error state at the start of this function. - * F_file_closed (with error bit) if the file is closed. - * F_file_read (with error bit) on file read error. - * F_parameter (with error bit) if a parameter is invalid. - * - * Errors (with error bit) from: f_string_dynamic_increase_by(). - * - * @see feof_unlocked() - * @see ferror_unlocked() - * @see flockfile() - * @see fread_unlocked() - * @see funlockfile() - * - * @see f_string_dynamic_increase_by() - */ -#ifndef _di_f_file_stream_read_until_ - extern f_status_t f_file_stream_read_until(const f_file_t file, const f_array_length_t total, f_string_dynamic_t * const buffer); -#endif // _di_f_file_stream_read_until_ - -/** - * Re-open a file stream. - * - * This allows for re-using an existing file stream and possibly file-descriptor. - * - * The file descriptor is retrieved on success, if necessary and able. - * - * @param path - * The file path. - * Set path.used to 0 with a non-empty mode (mode.used > 0) to only change the mode of the existing stream. - * @param mode - * The file modes do use when opening. - * Set to 0 to determine mode from file.flags (falling back to read only as a failsafe). - * If neither truncate nor append are not specified in write only mode, then the failsafe is to append. - * @param file - * The file information. - * The file.stream is updated, if necessary. - * - * @return - * F_none is returned on success. - * F_data_not if both path.used and mode.used are 0. - * - * F_access_denied (with error bit) on access denied. - * F_buffer (with error bit) if the buffer is invalid. - * F_busy (with error bit) if file system is too busy to perform write. - * F_file_descriptor (with error bit) if unable to load the file descriptor. - * F_file_found_not (with error bit) if the file was not found. - * F_file_open_max (with error bit) when system-wide max open files is reached. - * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. - * F_filesystem_quota_block (with error bit) if file system's disk blocks or inodes are exhausted. - * F_interrupt (with error bit) when program received an interrupt signal, halting operation. - * F_loop (with error bit) on loop error. - * F_memory_not (with error bit) if out of memory. - * F_name (with error bit) on path name is too long. - * F_number_overflow (with error bit) on overflow error. - * F_parameter (with error bit) if a parameter is invalid. - * F_prohibited (with error bit) if file system does not allow for making changes. - * F_read_only (with error bit) if file is read-only. - * F_supported_not (with error bit) fo unsupported file types. - * F_failure (with error bit) for any other error. - * - * @see fileno() - * @see freopen() - */ -#ifndef _di_f_file_stream_reopen_ - extern f_status_t f_file_stream_reopen(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file); -#endif // _di_f_file_stream_reopen_ - -/** - * Write until entire buffer is written. - * - * @param file - * The file to write to. - * The file must already be open. - * The file.size_write represents the amount to process at a given time. - * @param buffer - * The buffer to write to the file. - * @param written - * (optional) The total bytes written. - * Set to NULL to not use. - * - * @return - * F_none on success. - * F_none_eof when the file stream is at the end of the file. - * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). - * F_data_not on success but buffer.used is 0. - * F_stream_not if file.stream is NULL. - * - * F_file_write (with error bit) on error during file write. - * F_parameter (with error bit) if a parameter is invalid. - * - * F_file_write (with error bit) on any other error. - * - * @see ferror_unlocked() - * @see flockfile() - * @see fwrite_unlocked() - * @see funlockfile() - */ -#ifndef _di_f_file_stream_write_ - extern f_status_t f_file_stream_write(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written); -#endif // _di_f_file_stream_write_ - -/** - * Write until a single block is filled or entire buffer is written. - * - * To check how much was write into the buffer, record buffer->used before execution and compare to buffer->used after execution. - * - * @param file - * The file to write to. - * The file must already be open. - * The file.size_write represents the amount to process at a given time. - * @param buffer - * The buffer to write to the file. - * @param written - * (optional) The total bytes written. - * Set to NULL to not use. - * - * @return - * F_none on success. - * F_none_eof when the file stream is at the end of the file. - * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). - * F_data_not on success but buffer.used is 0. - * F_stream_not if file.stream is NULL. - * - * F_file_write (with error bit) on error during file write. - * F_parameter (with error bit) if a parameter is invalid. - * - * F_file_write (with error bit) on any other error. - * - * @see flockfile() - * @see fwrite_unlocked() - * @see ferror_unlocked() - * @see funlockfile() - */ -#ifndef _di_f_file_stream_write_block_ - extern f_status_t f_file_stream_write_block(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written); -#endif // _di_f_file_stream_write_block_ - -/** - * Write until a given number or entire buffer is written. - * - * @param file - * The file to write to. - * The file must already be open. - * The file.size_write represents the amount to process at a given time. - * @param buffer - * The buffer to write to the file. - * @param total - * The total bytes to write, unless end of buffer is reached first. - * @param written - * (optional) The total bytes written. - * Set to NULL to not use.. - * - * @return - * F_none on success. - * F_none_eof when the file stream is at the end of the file. - * F_none_eos on success but range.stop exceeded buffer.used (only wrote up to buffer.used). - * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). - * F_data_not on success but either buffer.used or total is 0. - * F_stream_not if file.stream is NULL. - * - * F_file_write (with error bit) on error during file write. - * F_parameter (with error bit) if a parameter is invalid. - * - * F_file_write (with error bit) on any other error. - * - * @see flockfile() - * @see fwrite_unlocked() - * @see ferror_unlocked() - * @see funlockfile() - */ -#ifndef _di_f_file_stream_write_until_ - extern f_status_t f_file_stream_write_until(const f_file_t file, const f_string_static_t buffer, const f_array_length_t total, f_array_length_t * const written); -#endif // _di_f_file_stream_write_until_ - -/** - * Write a given range within the buffer. - * - * @param file - * The file to write to. - * The file.size_write represents the amount to process at a given time. - * @param buffer - * The buffer to write to the file. - * @param range - * An inclusive start an stop range within the buffer to read. - * @param written - * (optional) The total bytes written. - * Set to NULL to not use. - * - * @return - * F_none on success. - * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). - * F_none_eos on success but range.stop exceeded buffer.used (only wrote up to buffer.used). - * F_stream_not if file.stream is NULL. - * - * F_file_write (with error bit) on error during file write. - * F_parameter (with error bit) if a parameter is invalid. - * - * @see fwrite_unlocked() - */ -#ifndef _di_f_file_stream_write_range_ - extern f_status_t f_file_stream_write_range(const f_file_t file, const f_string_static_t buffer, const f_string_range_t range, f_array_length_t * const written); -#endif // _di_f_file_stream_write_range_ - - -/** * Update the files access and modification timestamp, creating the file if it does not already exist. * * When the file is created, it is created as a regular file. diff --git a/level_0/f_file/c/file/common.h b/level_0/f_file/c/file/common.h index b7f197f..b1883fe 100644 --- a/level_0/f_file/c/file/common.h +++ b/level_0/f_file/c/file/common.h @@ -670,4 +670,4 @@ extern "C" { } // extern "C" #endif -#endif // _F_file_h +#endif // _F_file_common_h diff --git a/level_0/f_file/c/file/stream.c b/level_0/f_file/c/file/stream.c new file mode 100644 index 0000000..5938412 --- /dev/null +++ b/level_0/f_file/c/file/stream.c @@ -0,0 +1,558 @@ +#include "../file.h" +#include "stream.h" +#include "../private-file.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_f_file_stream_close_ + f_status_t f_file_stream_close(f_file_t * const file) { + #ifndef _di_level_0_parameter_checking_ + if (!file) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!file->stream) return F_stream_not; + + if (fclose(file->stream) == EOF) { + + // According to man pages, further access to a stream on error results in undefined behavior. + file->stream = 0; + + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == EFBIG) return F_status_set_error(F_file_overflow); + if (errno == EDEADLK) return F_status_set_error(F_deadlock); + if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); + if (errno == EDQUOT) return F_status_set_error(F_space_not); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); + if (errno == ENOLCK) return F_status_set_error(F_lock); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EPIPE) return F_status_set_error(F_pipe_not); + + return F_status_set_error(F_file_close); + } + + file->stream = 0; + + return F_none; + } +#endif // _di_f_file_stream_close_ + +#ifndef _di_f_file_stream_flush_ + f_status_t f_file_stream_flush(const f_file_t file) { + + if (!file.stream) return F_stream_not; + + // Only 0 is considered a success and so any non-zero value could be an error. + if (fflush(file.stream) != 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EISDIR) return F_status_set_error(F_file_type_directory); + + return F_status_set_error(F_file_synchronize); + } + + return F_none; + } +#endif // _di_f_file_stream_flush_ + +#ifndef _di_f_file_stream_lock_ + f_status_t f_file_stream_lock(const f_file_t file) { + + if (!file.stream) return F_stream_not; + + flockfile(file.stream); + + return F_none; + } +#endif // _di_f_file_stream_lock_ + +#ifndef _di_f_file_stream_lock_try_ + f_status_t f_file_stream_lock_try(const f_file_t file) { + + if (!file.stream) return F_stream_not; + + if (ftrylockfile(file.stream)) return F_busy; + + return F_none; + } +#endif // _di_f_file_stream_lock_try_ + +#ifndef _di_f_file_stream_open_ + f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file) { + #ifndef _di_level_0_parameter_checking_ + if (!file) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!path.used) return F_data_not; + + if (mode.used) { + file->stream = fopen(path.string, mode.string); + } + else { + file->stream = fopen(path.string, private_f_file_stream_open_mode_determine(file->flag)); + } + + if (!file->stream) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block); + if (errno == EEXIST) return F_status_set_error(F_file_found); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EFBIG || errno == EOVERFLOW) return F_status_set_error(F_number_overflow); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ELOOP) return F_status_set_error(F_loop); + if (errno == ENFILE) return F_status_set_error(F_file_open_max); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == ETXTBSY) return F_status_set_error(F_busy); + if (errno == EISDIR) return F_status_set_error(F_directory); + if (errno == EOPNOTSUPP) return F_status_set_error(F_supported_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_file_stream_open_ + +#ifndef _di_f_file_stream_open_descriptor_ + f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file) { + #ifndef _di_level_0_parameter_checking_ + if (!file) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (file->id == -1) return F_file_descriptor_not; + + if (mode.used) { + file->stream = fdopen(file->id, private_f_file_stream_open_mode_determine(file->flag)); + } + else { + file->stream = fdopen(file->id, mode.string); + } + + if (!file->stream) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == EFBIG) return F_status_set_error(F_file_overflow); + if (errno == EDEADLK) return F_status_set_error(F_deadlock); + if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); + if (errno == EDQUOT) return F_status_set_error(F_space_not); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); + if (errno == ENODEV) return F_status_set_error(F_device_not); + if (errno == ENOLCK) return F_status_set_error(F_lock); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EPIPE) return F_status_set_error(F_pipe_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_file_stream_open_descriptor_ + +#ifndef _di_f_file_stream_read_ + f_status_t f_file_stream_read(const f_file_t file, f_string_dynamic_t * const buffer) { + #ifndef _di_level_0_parameter_checking_ + if (!file.size_read) return F_status_set_error(F_parameter); + if (!buffer) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!file.stream) return F_stream_not; + + flockfile(file.stream); + + if (feof_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_none_eof; + } + + if (ferror_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_status_set_error(F_error); + } + + f_status_t status = F_none; + size_t size_read = 0; + + do { + status = f_string_dynamic_increase_by(file.size_read, buffer); + + if (F_status_is_error(status)) { + funlockfile(file.stream); + + return status; + } + + size_read = fread_unlocked(buffer->string + buffer->used, sizeof(f_char_t), file.size_read, file.stream); + + if (ferror_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_status_set_error(F_file_read); + } + + buffer->used += size_read; + + } while (size_read == file.size_read && !feof_unlocked(file.stream)); + + funlockfile(file.stream); + + return F_none_eof; + } +#endif // _di_f_file_stream_read_ + +#ifndef _di_f_file_stream_read_block_ + f_status_t f_file_stream_read_block(const f_file_t file, f_string_dynamic_t * const buffer) { + #ifndef _di_level_0_parameter_checking_ + if (!file.size_read) return F_status_set_error(F_parameter); + if (!buffer) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!file.stream) return F_stream_not; + + flockfile(file.stream); + + if (feof_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_none_eof; + } + + if (ferror_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_status_set_error(F_error); + } + + { + const f_status_t status = f_string_dynamic_increase_by(file.size_read, buffer); + + if (F_status_is_error(status)) { + funlockfile(file.stream); + + return status; + } + } + + const size_t size_read = fread_unlocked(buffer->string + buffer->used, sizeof(f_char_t), file.size_read, file.stream); + + if (ferror_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_status_set_error(F_file_read); + } + + if (size_read) { + buffer->used += size_read; + } + + if (feof_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_none_eof; + } + + funlockfile(file.stream); + + return F_none; + } +#endif // _di_f_file_stream_read_block_ + +#ifndef _di_f_file_stream_read_until_ + f_status_t f_file_stream_read_until(const f_file_t file, const f_array_length_t total, f_string_dynamic_t * const buffer) { + #ifndef _di_level_0_parameter_checking_ + if (!file.size_read) return F_status_set_error(F_parameter); + if (!buffer) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!file.stream) return F_stream_not; + if (!total) return F_data_not; + + flockfile(file.stream); + + if (feof_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_none_eof; + } + + if (ferror_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_status_set_error(F_error); + } + + { + const f_status_t status = f_string_dynamic_increase_by(total, buffer); + + if (F_status_is_error(status)) { + funlockfile(file.stream); + + return F_none_eof; + } + } + + f_array_length_t buffer_size = file.size_read; + f_array_length_t buffer_count = 0; + + size_t size_read = 0; + + for (;;) { + + if (buffer_count + buffer_size > total) { + buffer_size = total - buffer_count; + } + + size_read = fread_unlocked(buffer->string + buffer->used, sizeof(f_char_t), buffer_size, file.stream); + + if (ferror_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_status_set_error(F_file_read); + } + + buffer->used += size_read; + + if (feof_unlocked(file.stream)) { + funlockfile(file.stream); + + return F_none_eof; + } + + buffer_count += size_read; + + if (buffer_count >= total) break; + } // for + + funlockfile(file.stream); + + return F_none_stop; + } +#endif // _di_f_file_stream_read_until_ + +#ifndef _di_f_file_stream_reopen_ + f_status_t f_file_stream_reopen(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file) { + #ifndef _di_level_0_parameter_checking_ + if (!file) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!path.used && !mode.used) return F_data_not; + + FILE *result = 0; + + if (mode.used) { + result = freopen(path.used ? path.string : 0, mode.string, file->stream); + } + else { + result = freopen(path.used ? path.string : 0, private_f_file_stream_open_mode_determine(file->flag), file->stream); + } + + if (!result) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == EFBIG) return F_status_set_error(F_file_overflow); + if (errno == EDEADLK) return F_status_set_error(F_deadlock); + if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not); + if (errno == EDQUOT) return F_status_set_error(F_space_not); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EIO) return F_status_set_error(F_input_output); + if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); + if (errno == ENOLCK) return F_status_set_error(F_lock); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EPIPE) return F_status_set_error(F_pipe_not); + + return F_status_set_error(F_failure); + } + + file->stream = result; + + return F_none; + } +#endif // _di_f_file_stream_reopen_ + +#ifndef _di_f_file_stream_unlock_ + f_status_t f_file_stream_unlock(const f_file_t file) { + + if (!file.stream) return F_stream_not; + + funlockfile(file.stream); + + return F_none; + } +#endif // _di_f_file_stream_unlock_ + +#ifndef _di_f_file_stream_write_ + f_status_t f_file_stream_write(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written) { + + if (!file.stream || !buffer.used || !file.size_write) { + if (written) { + *written = 0; + } + + return file.stream ? F_data_not : F_stream_not; + } + + if (written) { + const f_status_t status = private_f_file_stream_write_until(file, buffer, buffer.used, written); + + if (status == F_none && *written == buffer.used) return F_none_eos; + } + else { + f_array_length_t written_local = 0; + + const f_status_t status = private_f_file_stream_write_until(file, buffer, buffer.used, &written_local); + + if (status == F_none && written_local == buffer.used) return F_none_eos; + } + + return F_none; + } +#endif // _di_f_file_stream_write_ + +#ifndef _di_f_file_stream_write_block_ + f_status_t f_file_stream_write_block(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written) { + + if (!file.stream || !buffer.used || !file.size_write) { + if (written) { + *written = 0; + } + + return file.stream ? F_data_not : F_stream_not; + } + + const f_array_length_t write_max = file.size_write > buffer.used ? buffer.used : file.size_write; + + if (written) { + const f_status_t status = private_f_file_stream_write_until(file, buffer, write_max, written); + + if (status == F_none) { + if (*written == buffer.used) return F_none_eos; + if (*written == write_max) return F_none_stop; + } + } + else { + f_array_length_t written_local = 0; + + const f_status_t status = private_f_file_stream_write_until(file, buffer, write_max, &written_local); + + if (status == F_none) { + if (written_local == buffer.used) return F_none_eos; + if (written_local == write_max) return F_none_stop; + } + } + + return F_none; + } +#endif // _di_f_file_stream_write_block_ + +#ifndef _di_f_file_stream_write_until_ + f_status_t f_file_stream_write_until(const f_file_t file, const f_string_static_t buffer, const f_array_length_t total, f_array_length_t * const written) { + + if (!file.stream || !buffer.used || !total || !file.size_write) { + if (written) { + *written = 0; + } + + return file.stream ? F_data_not : F_stream_not; + } + + const f_array_length_t write_max = total > buffer.used ? buffer.used : total; + + if (written) { + const f_status_t status = private_f_file_stream_write_until(file, buffer, write_max, written); + + if (status == F_none) { + if (*written == buffer.used) return F_none_eos; + if (*written == write_max) return F_none_stop; + } + } + else { + f_array_length_t written_local = 0; + + const f_status_t status = private_f_file_stream_write_until(file, buffer, buffer.used, &written_local); + + if (status == F_none) { + if (written_local == buffer.used) return F_none_eos; + if (written_local == write_max) return F_none_stop; + } + } + + return F_none; + } +#endif // _di_f_file_stream_write_until_ + +#ifndef _di_f_file_stream_write_range_ + f_status_t f_file_stream_write_range(const f_file_t file, const f_string_static_t buffer, const f_string_range_t range, f_array_length_t * const written) { + + if (!file.stream || !buffer.used || range.start > range.stop || range.start >= buffer.used || !file.size_write) { + if (written) { + *written = 0; + } + + return file.stream ? F_data_not : F_stream_not; + } + + const f_array_length_t write_max = (range.stop - range.start) + 1 > buffer.used ? buffer.used : (range.stop - range.start) + 1; + + if (written) { + const f_string_static_t buffer_adjusted = macro_f_string_static_t_initialize(buffer.string + range.start, 0, buffer.used - range.start); + + const f_status_t status = private_f_file_stream_write_until(file, buffer_adjusted, write_max, written); + + if (status == F_none) { + if (range.start + *written == buffer.used) return F_none_eos; + if (range.start + *written == write_max) return F_none_stop; + } + } + else { + const f_string_static_t buffer_adjusted = macro_f_string_static_t_initialize(buffer.string + range.start, 0, buffer.used - range.start); + f_array_length_t written_local = 0; + + const f_status_t status = private_f_file_stream_write_until(file, buffer_adjusted, write_max, &written_local); + + if (status == F_none) { + if (range.start + written_local == buffer.used) return F_none_eos; + if (range.start + written_local == write_max) return F_none_stop; + } + } + + return F_none; + } +#endif // _di_f_file_stream_write_range_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_file/c/file/stream.h b/level_0/f_file/c/file/stream.h new file mode 100644 index 0000000..a5b3fc0 --- /dev/null +++ b/level_0/f_file/c/file/stream.h @@ -0,0 +1,528 @@ +/** + * FLL - Level 0 + * + * Project: File + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Defines common data to be used for/by project file. + * + * This is auto-included by file.h and should not need to be explicitly included. + */ +#ifndef _F_file_stream_h +#define _F_file_stream_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Close an open file stream. + * + * @param file + * The file information. + * The file.stream is set to NULL, on both success or on failure. + * + * @return + * F_none on success. + * F_stream_not if file.stream is NULL. + * + * F_access_denied (with error bit) on access denied. + * F_block (with error bit) if the action would block and non-blocking is set on the stream. + * F_buffer (with error bit) if the buffer is invalid. + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_file_descriptor (with error bit) if file descriptor is invalid. + * F_file_descriptor_max (with error bit) if max file descriptors is reached. + * F_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size. + * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) when program received an interrupt signal, halting operation. + * F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed. + * F_space_not (with error bit) if file system is out of space (or file system quota is reached). + * F_socket_not (with error bit) if the datagram socket in which a peer has not been set (for socket related streams). + * + * F_file_close (with error bit) on any other error. + * + * @see fclose() + */ +#ifndef _di_f_file_stream_close_ + extern f_status_t f_file_stream_close(f_file_t * const file); +#endif // _di_f_file_stream_close_ + +/** + * Flush a file stream. + * + * @param file + * The file information. + * The file.id is updated with the file descriptor, if necessary and able. + * + * @return + * F_none is returned on success. + * F_stream_not if file.stream is NULL. + * F_file_descriptor_not if file.id is -1. + * + * F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * + * F_file_synchronize (with error bit) on any other error. + * + * @see fflush() + */ +#ifndef _di_f_file_stream_flush_ + extern f_status_t f_file_stream_flush(const f_file_t file); +#endif // _di_f_file_stream_flush_ + +/** + * Lock a file stream. + * + * As per flockfile(), this waits (blocks) until the file stream is available to lock again. + * + * @param file + * The file to lock. + * + * @return + * F_none on success. + * F_stream_not if file.stream is NULL. + * + * @see flockfile() + */ +#ifndef _di_f_file_stream_lock_ + extern f_status_t f_file_stream_lock(const f_file_t file); +#endif // _di_f_file_stream_lock_ + +/** + * Try to lock a file stream. + * + * As per flockfile(), this does not wait (does not block) when the file stream is already locked. + * + * @param file + * The file to lock. + * + * @return + * F_none on success. + * F_busy on success, but the file.stream is already locked. + * F_stream_not if file.stream is NULL. + * + * @see ftrylockfile() + */ +#ifndef _di_f_file_stream_lock_try_ + extern f_status_t f_file_stream_lock_try(const f_file_t file); +#endif // _di_f_file_stream_lock_try_ + +/** + * Open a file stream. + * + * The file descriptor is retrieved on success, if necessary and able. + * + * If the file stream is open, it is closed before re-opening. + * + * This is often used for changing the file pointed to by standard streams such as stdout. + * + * @param path + * The file path. + * @param mode + * The file modes do use when opening, as an fopen() file mode string. + * Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe). + * If neither truncate nor append are specified in write only mode, then the failsafe is to append. + * + * File Modes (fopen() file modes vs open file modes): + * - "r": O_RDONLY. + * - "w": O_WRONLY | O_CREAT | O_TRUNC. + * - "a": O_WRONLY | O_CREAT | O_APPEND. + * - "r+": O_RDWR. + * - "w+": O_RDWR | O_CREAT | O_TRUNC. + * - "a+": O_RDWR | O_CREAT | O_APPEND. + * @param file + * The file information. + * The file.stream is updated if necessary. + * The file.id is updated with the file descriptor, if necessary and able. + * + * @return + * F_none is returned on success. + * F_data_not if both path.used is 0. + * + * F_access_denied (with error bit) on access denied. + * F_buffer (with error bit) if the buffer is invalid. + * F_busy (with error bit) if file system is too busy to perform write. + * F_file_descriptor (with error bit) if unable to load the file descriptor. + * F_file_found_not (with error bit) if the file was not found. + * F_file_open_max (with error bit) when system-wide max open files is reached. + * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. + * F_filesystem_quota_block (with error bit) if file system's disk blocks or inodes are exhausted. + * F_interrupt (with error bit) when program received an interrupt signal, halting operation. + * F_loop (with error bit) on loop error. + * F_memory_not (with error bit) if out of memory. + * F_name (with error bit) on path name is too long. + * F_number_overflow (with error bit) on overflow error. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if file system does not allow for making changes. + * F_read_only (with error bit) if file is read-only. + * F_supported_not (with error bit) fo unsupported file types. + * F_failure (with error bit) for any other error. + * + * @see fopen() + */ +#ifndef _di_f_file_stream_open_ + extern f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file); +#endif // _di_f_file_stream_open_ + +/** + * Open a file stream from a file descriptor. + * + * @param mode + * The file modes do use when opening. + * Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe). + * If neither truncate nor append are not specified in write only mode, then the failsafe is to append. + * This should match the modes used to open the file descriptor as it relates to the stream modes. + * @param file + * The file with a valid file descriptor (file.id). + * + * @return + * F_none is returned on success. + * F_file_descriptor_not if file.id is -1. + * + * F_access_denied (with error bit) on access denied. + * F_block (with error bit) if the action would block and non-blocking is set on the stream. + * F_buffer (with error bit) if the buffer is invalid. + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_file_descriptor (with error bit) if file descriptor is invalid. + * F_file_descriptor_max (with error bit) if max file descriptors is reached. + * F_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size. + * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. + * F_interrupt (with error bit) when program received an interrupt signal, halting operation. + * F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed. + * F_prohibited (with error bit) if file system does not allow for making changes. + * F_socket_not (with error bit) if socket is not connected. + * F_space_not (with error bit) if the file system is out of space (or file system quota is reached). + * + * @see fdopen() + */ +#ifndef _di_f_file_stream_open_descriptor_ + extern f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file); +#endif // _di_f_file_stream_open_descriptor_ + +/** + * Read until EOF is reached. + * + * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. + * + * @param file + * The file to read. + * The file.size_read represents the amount to process at a given time. + * @param buffer + * The buffer the file is being read into. + * The contents of the file is appended into this buffer. + * + * @return + * F_none_eof on success and EOF was reached. + * F_stream_not if file.stream is NULL. + * + * F_block (with error bit) if file descriptor is set to non-block and the read would result in a blocking operation. + * F_buffer (with error bit) if the buffer is invalid. + * F_error (with error bit) if the file is already in the error state at the start of this function. + * F_file_closed (with error bit) if file is not open. + * F_file_descriptor (with error bit) if the file descriptor is invalid. + * F_file_type_directory (with error bit) if file descriptor represents a directory. + * F_input_output (with error bit) on I/O error. + * F_interrupt (with error bit) if interrupt was received. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see flockfile() + * @see feof_unlocked() + * @see ferror_unlocked() + * @see fread_unlocked() + * @see funlockfile() + */ +#ifndef _di_f_file_stream_read_ + extern f_status_t f_file_stream_read(const f_file_t file, f_string_dynamic_t * const buffer); +#endif // _di_f_file_stream_read_ + +/** + * Read until a single block is filled or EOF is reached. + * + * To determine how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. + * + * @param file + * The file to read. + * The file.size_read represents the amount to process at a given time. + * @param buffer + * The buffer the file is being read into. + * The contents of the file is appended into this buffer. + * + * @return + * F_none on success. + * F_none_eof on success and EOF was reached. + * F_stream_not if file.stream is NULL. + * + * F_error (with error bit) if the file is already in the error state at the start of this function. + * F_file_closed (with error bit) if the file is closed. + * F_file_read (with error bit) on file read error. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see feof_unlocked() + * @see ferror_unlocked() + * @see flockfile() + * @see fread() + * @see funlockfile() + */ +#ifndef _di_f_file_stream_read_block_ + extern f_status_t f_file_stream_read_block(const f_file_t file, f_string_dynamic_t * const buffer); +#endif // _di_f_file_stream_read_block_ + +/** + * Read until a given number or EOF is reached, storing it in the buffer. + * + * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. + * + * This is different from simply using the file.size_read. + * The file.size_read represents the amount to process at a given time. + * The total represents the maximum number of file.size_read to process. + * For example, if file.size_read is 16 and total is 128, then this function would need to be called 8 times until total is reached. + * + * @param file + * The file to read. + * The file.size_read represents the amount to process at a given time. + * @param total + * The total bytes to read, unless EOF is reached first. + * @param buffer + * The buffer the file is being read into. + * + * @return + * F_none_eof on success and EOF was reached. + * F_none_stop on success and total was reached. + * F_data_not if total is 0. + * F_stream_not if file.stream is NULL. + * + * F_error (with error bit) if the file is already in the error state at the start of this function. + * F_file_closed (with error bit) if the file is closed. + * F_file_read (with error bit) on file read error. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_string_dynamic_increase_by(). + * + * @see feof_unlocked() + * @see ferror_unlocked() + * @see flockfile() + * @see fread_unlocked() + * @see funlockfile() + * + * @see f_string_dynamic_increase_by() + */ +#ifndef _di_f_file_stream_read_until_ + extern f_status_t f_file_stream_read_until(const f_file_t file, const f_array_length_t total, f_string_dynamic_t * const buffer); +#endif // _di_f_file_stream_read_until_ + +/** + * Re-open a file stream. + * + * This allows for re-using an existing file stream and possibly file-descriptor. + * + * The file descriptor is retrieved on success, if necessary and able. + * + * @param path + * The file path. + * Set path.used to 0 with a non-empty mode (mode.used > 0) to only change the mode of the existing stream. + * @param mode + * The file modes do use when opening. + * Set to 0 to determine mode from file.flags (falling back to read only as a failsafe). + * If neither truncate nor append are not specified in write only mode, then the failsafe is to append. + * @param file + * The file information. + * The file.stream is updated, if necessary. + * + * @return + * F_none is returned on success. + * F_data_not if both path.used and mode.used are 0. + * + * F_access_denied (with error bit) on access denied. + * F_buffer (with error bit) if the buffer is invalid. + * F_busy (with error bit) if file system is too busy to perform write. + * F_file_descriptor (with error bit) if unable to load the file descriptor. + * F_file_found_not (with error bit) if the file was not found. + * F_file_open_max (with error bit) when system-wide max open files is reached. + * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory. + * F_filesystem_quota_block (with error bit) if file system's disk blocks or inodes are exhausted. + * F_interrupt (with error bit) when program received an interrupt signal, halting operation. + * F_loop (with error bit) on loop error. + * F_memory_not (with error bit) if out of memory. + * F_name (with error bit) on path name is too long. + * F_number_overflow (with error bit) on overflow error. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if file system does not allow for making changes. + * F_read_only (with error bit) if file is read-only. + * F_supported_not (with error bit) fo unsupported file types. + * F_failure (with error bit) for any other error. + * + * @see fileno() + * @see freopen() + */ +#ifndef _di_f_file_stream_reopen_ + extern f_status_t f_file_stream_reopen(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file); +#endif // _di_f_file_stream_reopen_ + +/** + * Unlock a locked file stream. + * + * @param file + * The file to unlock. + * + * @return + * F_none on success. + * F_stream_not if file.stream is NULL. + * + * @see funlockfile() + */ +#ifndef _di_f_file_stream_unlock_ + extern f_status_t f_file_stream_unlock(const f_file_t file) ; +#endif // _di_f_file_stream_unlock_ + +/** + * Write until entire buffer is written. + * + * @param file + * The file to write to. + * The file must already be open. + * The file.size_write represents the amount to process at a given time. + * @param buffer + * The buffer to write to the file. + * @param written + * (optional) The total bytes written. + * Set to NULL to not use. + * + * @return + * F_none on success. + * F_none_eof when the file stream is at the end of the file. + * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). + * F_data_not on success but buffer.used is 0. + * F_stream_not if file.stream is NULL. + * + * F_file_write (with error bit) on error during file write. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_file_write (with error bit) on any other error. + * + * @see ferror_unlocked() + * @see flockfile() + * @see fwrite_unlocked() + * @see funlockfile() + */ +#ifndef _di_f_file_stream_write_ + extern f_status_t f_file_stream_write(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written); +#endif // _di_f_file_stream_write_ + +/** + * Write until a single block is filled or entire buffer is written. + * + * To check how much was write into the buffer, record buffer->used before execution and compare to buffer->used after execution. + * + * @param file + * The file to write to. + * The file must already be open. + * The file.size_write represents the amount to process at a given time. + * @param buffer + * The buffer to write to the file. + * @param written + * (optional) The total bytes written. + * Set to NULL to not use. + * + * @return + * F_none on success. + * F_none_eof when the file stream is at the end of the file. + * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). + * F_data_not on success but buffer.used is 0. + * F_stream_not if file.stream is NULL. + * + * F_file_write (with error bit) on error during file write. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_file_write (with error bit) on any other error. + * + * @see flockfile() + * @see fwrite_unlocked() + * @see ferror_unlocked() + * @see funlockfile() + */ +#ifndef _di_f_file_stream_write_block_ + extern f_status_t f_file_stream_write_block(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written); +#endif // _di_f_file_stream_write_block_ + +/** + * Write until a given number or entire buffer is written. + * + * @param file + * The file to write to. + * The file must already be open. + * The file.size_write represents the amount to process at a given time. + * @param buffer + * The buffer to write to the file. + * @param total + * The total bytes to write, unless end of buffer is reached first. + * @param written + * (optional) The total bytes written. + * Set to NULL to not use.. + * + * @return + * F_none on success. + * F_none_eof when the file stream is at the end of the file. + * F_none_eos on success but range.stop exceeded buffer.used (only wrote up to buffer.used). + * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). + * F_data_not on success but either buffer.used or total is 0. + * F_stream_not if file.stream is NULL. + * + * F_file_write (with error bit) on error during file write. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_file_write (with error bit) on any other error. + * + * @see flockfile() + * @see fwrite_unlocked() + * @see ferror_unlocked() + * @see funlockfile() + */ +#ifndef _di_f_file_stream_write_until_ + extern f_status_t f_file_stream_write_until(const f_file_t file, const f_string_static_t buffer, const f_array_length_t total, f_array_length_t * const written); +#endif // _di_f_file_stream_write_until_ + +/** + * Write a given range within the buffer. + * + * @param file + * The file to write to. + * The file.size_write represents the amount to process at a given time. + * @param buffer + * The buffer to write to the file. + * @param range + * An inclusive start an stop range within the buffer to read. + * @param written + * (optional) The total bytes written. + * Set to NULL to not use. + * + * @return + * F_none on success. + * F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file). + * F_none_eos on success but range.stop exceeded buffer.used (only wrote up to buffer.used). + * F_stream_not if file.stream is NULL. + * + * F_file_write (with error bit) on error during file write. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see fwrite_unlocked() + */ +#ifndef _di_f_file_stream_write_range_ + extern f_status_t f_file_stream_write_range(const f_file_t file, const f_string_static_t buffer, const f_string_range_t range, f_array_length_t * const written); +#endif // _di_f_file_stream_write_range_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_file_stream_h diff --git a/level_0/f_file/data/build/settings b/level_0/f_file/data/build/settings index 5e7561e..0ed2726 100644 --- a/level_0/f_file/data/build/settings +++ b/level_0/f_file/data/build/settings @@ -20,9 +20,9 @@ build_language c build_libraries -lc build_libraries-individual -lf_memory -lf_string -build_sources_library file.c private-file.c file/common.c +build_sources_library file.c private-file.c file/common.c file/stream.c -build_sources_headers file.h file/common.h +build_sources_headers file.h file/common.h file/stream.h build_script yes build_shared yes diff --git a/level_0/f_file/data/build/settings-mocks b/level_0/f_file/data/build/settings-mocks index d467aac..33eb429 100644 --- a/level_0/f_file/data/build/settings-mocks +++ b/level_0/f_file/data/build/settings-mocks @@ -30,9 +30,9 @@ build_language c build_libraries -lc build_libraries-individual -lf_memory -lf_string -build_sources_library file.c file/common.c private-file.c ../../tests/unit/c/mock-file.c +build_sources_library file.c file/common.c file/stream.c private-file.c ../../tests/unit/c/mock-file.c -build_sources_headers file.h file/common.h file/type.h +build_sources_headers file.h file/common.h file/stream.h file/type.h build_script yes build_shared yes diff --git a/level_0/f_memory/c/memory.c b/level_0/f_memory/c/memory.c index d6d3b59..9e9cc5b 100644 --- a/level_0/f_memory/c/memory.c +++ b/level_0/f_memory/c/memory.c @@ -94,6 +94,7 @@ extern "C" { f_status_t f_memory_new_aligned(const size_t length, const size_t alignment, void ** const pointer) { #ifndef _di_level_0_parameter_checking_ if (!alignment) return F_status_set_error(F_parameter); + if (!pointer) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ // Prevent double-allocations and unnecessary frees. diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 2b897fa..0e5cb97 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -372,6 +372,8 @@ extern "C" { F_no_not, F_object, F_object_not, + F_okay, + F_okay_not, F_once, F_once_not, F_option, diff --git a/level_0/f_status_string/c/status_string.c b/level_0/f_status_string/c/status_string.c index 20d6457..11b6260 100644 --- a/level_0/f_status_string/c/status_string.c +++ b/level_0/f_status_string/c/status_string.c @@ -246,6 +246,8 @@ extern "C" { const f_string_static_t f_status_no_not_s = macro_f_string_static_t_initialize(F_status_no_not_s, 0, F_status_no_not_s_length); const f_string_static_t f_status_object_s = macro_f_string_static_t_initialize(F_status_object_s, 0, F_status_object_s_length); const f_string_static_t f_status_object_not_s = macro_f_string_static_t_initialize(F_status_object_not_s, 0, F_status_object_not_s_length); + const f_string_static_t f_status_okay_s = macro_f_string_static_t_initialize(F_status_okay_s, 0, F_status_okay_s_length); + const f_string_static_t f_status_okay_not_s = macro_f_string_static_t_initialize(F_status_okay_not_s, 0, F_status_okay_not_s_length); const f_string_static_t f_status_once_s = macro_f_string_static_t_initialize(F_status_once_s, 0, F_status_once_s_length); const f_string_static_t f_status_once_not_s = macro_f_string_static_t_initialize(F_status_once_not_s, 0, F_status_once_not_s_length); const f_string_static_t f_status_option_s = macro_f_string_static_t_initialize(F_status_option_s, 0, F_status_option_s_length); @@ -1821,6 +1823,16 @@ extern "C" { break; + case F_okay: + *name = f_status_okay_s; + + break; + + case F_okay_not: + *name = f_status_okay_not_s; + + break; + case F_once: *name = f_status_once_s; diff --git a/level_0/f_status_string/c/status_string.h b/level_0/f_status_string/c/status_string.h index b8199dd..56bea80 100644 --- a/level_0/f_status_string/c/status_string.h +++ b/level_0/f_status_string/c/status_string.h @@ -399,6 +399,8 @@ extern "C" { #define F_status_no_not_s "F_no_not" #define F_status_object_s "F_object" #define F_status_object_not_s "F_object_not" + #define F_status_okay_s "F_okay" + #define F_status_okay_not_s "F_okay_not" #define F_status_once_s "F_once" #define F_status_once_not_s "F_once_not" #define F_status_option_s "F_option" @@ -695,6 +697,8 @@ extern "C" { #define F_status_no_not_s_length 8 #define F_status_object_s_length 8 #define F_status_object_not_s_length 12 + #define F_status_okay_s_length 6 + #define F_status_okay_not_s_length 10 #define F_status_once_s_length 6 #define F_status_once_not_s_length 10 #define F_status_option_s_length 8 @@ -993,6 +997,8 @@ extern "C" { extern const f_string_static_t f_status_no_not_s; extern const f_string_static_t f_status_object_s; extern const f_string_static_t f_status_object_not_s; + extern const f_string_static_t f_status_okay_s; + extern const f_string_static_t f_status_okay_not_s; extern const f_string_static_t f_status_once_s; extern const f_string_static_t f_status_once_not_s; extern const f_string_static_t f_status_option_s; diff --git a/level_0/f_status_string/tests/unit/c/test-status_string-to.c b/level_0/f_status_string/tests/unit/c/test-status_string-to.c index 80f7e62..9e1064d 100644 --- a/level_0/f_status_string/tests/unit/c/test-status_string-to.c +++ b/level_0/f_status_string/tests/unit/c/test-status_string-to.c @@ -262,6 +262,8 @@ void test__f_status_string_to__works(void **state) { F_no_not, F_object, F_object_not, + F_okay, + F_okay_not, F_once, F_once_not, F_option, @@ -854,6 +856,8 @@ void test__f_status_string_to__works(void **state) { f_status_no_not_s, f_status_object_s, f_status_object_not_s, + f_status_okay_s, + f_status_okay_not_s, f_status_once_s, f_status_once_not_s, f_status_option_s, @@ -1213,7 +1217,7 @@ void test__f_status_string_to__works(void **state) { f_status_status_code_last_s, }; - for (uint16_t i = 0; i < 589; ++i) { + for (uint16_t i = 0; i < 591; ++i) { f_string_static_t result = f_string_static_t_initialize; diff --git a/level_2/fll_program/c/private-program.c b/level_2/fll_program/c/private-program.c index 2971f69..72c2fe9 100644 --- a/level_2/fll_program/c/private-program.c +++ b/level_2/fll_program/c/private-program.c @@ -6,10 +6,10 @@ extern "C" { #endif #if !defined(_di_fll_program_print_help_option_) || !defined(_di_fll_program_print_help_option_standard_) - f_status_t private_fll_program_print_help_option(const f_file_t output, const f_color_context_t context, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description) { + f_status_t private_fll_program_print_help_option(const fl_print_t print, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description) { - fl_print_format("%r %Q%[%Q%]", output.stream, f_string_eol_s, symbol_short, context.set.standout, option_short, context.set.standout); - fl_print_format(", %Q%[%Q%] %S", output.stream, symbol_long, context.set.standout, option_long, context.set.standout, description); + fl_print_format("%r %Q%[%Q%]", print.to.stream, f_string_eol_s, symbol_short, print.set->standout, option_short, print.set->standout); + fl_print_format(", %Q%[%Q%] %S", print.to.stream, symbol_long, print.set->standout, option_long, print.set->standout, description); return F_none; } diff --git a/level_2/fll_program/c/private-program.h b/level_2/fll_program/c/private-program.h index 79c86da..b433bfb 100644 --- a/level_2/fll_program/c/private-program.h +++ b/level_2/fll_program/c/private-program.h @@ -20,10 +20,8 @@ extern "C" { * * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. * - * @param output - * The file stream to output to. - * @param context - * The color context. + * @param print + * The output structure to print to. * @param option_short * The short name of the option. * @param option_long @@ -45,7 +43,7 @@ extern "C" { * @see fll_program_print_help_option_standard() */ #if !defined(_di_fll_program_print_help_option_) || !defined(_di_fll_program_print_help_option_standard_) - extern f_status_t private_fll_program_print_help_option(const f_file_t output, const f_color_context_t context, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description) F_attribute_visibility_internal_d; + extern f_status_t private_fll_program_print_help_option(const fl_print_t print, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description) F_attribute_visibility_internal_d; #endif // !defined(_di_fll_program_print_help_option_) || !defined(_di_fll_program_print_help_option_standard_) /** diff --git a/level_2/fll_program/c/program.c b/level_2/fll_program/c/program.c index 7ba650f..d3afb00 100644 --- a/level_2/fll_program/c/program.c +++ b/level_2/fll_program/c/program.c @@ -5,91 +5,6 @@ extern "C" { #endif -#ifndef _di_fll_program_print_help_header_ - f_status_t fll_program_print_help_header(const f_file_t output, const f_color_context_t context, const f_string_static_t name, const f_string_static_t version) { - - fl_print_format(" %[%Q%]%r", output.stream, context.set.title, name, context.set.title, f_string_eol_s); - fl_print_format(" %[Version %Q%]%r", output.stream, context.set.notable, version, context.set.notable, f_string_eol_s); - - fl_print_format("%r %[Available Options:%] ", output.stream, f_string_eol_s, context.set.important, context.set.important); - - return F_none; - } -#endif // _di_fll_program_print_help_header_ - -#ifndef _di_fll_program_print_help_option_ - f_status_t fll_program_print_help_option(const f_file_t output, const f_color_context_t context, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description) { - - return private_fll_program_print_help_option(output, context, option_short, option_long, symbol_short, symbol_long, description); - } -#endif // _di_fll_program_print_help_option_ - -#ifndef _di_fll_program_print_help_option_standard_ - f_status_t fll_program_print_help_option_standard(const f_file_t output, const f_color_context_t context) { - - private_fll_program_print_help_option(output, context, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message."); - private_fll_program_print_help_option(output, context, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds."); - private_fll_program_print_help_option(output, context, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds."); - private_fll_program_print_help_option(output, context, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Do not print using color."); - private_fll_program_print_help_option(output, context, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, silencing most output."); - private_fll_program_print_help_option(output, context, f_console_standard_short_error_s, f_console_standard_long_error_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, using only error output."); - private_fll_program_print_help_option(output, context, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal."); - private_fll_program_print_help_option(output, context, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal output."); - private_fll_program_print_help_option(output, context, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, significantly increasing verbosity beyond normal output."); - private_fll_program_print_help_option(output, context, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number."); - private_fll_program_print_help_option(output, context, f_console_standard_short_line_first_no_s, f_console_standard_long_line_first_no_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Disable printing of first line."); - private_fll_program_print_help_option(output, context, f_console_standard_short_line_last_no_s, f_console_standard_long_line_last_no_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Disable printing of last line."); - - return F_none; - } -#endif // _di_fll_program_print_help_option_standard_ - -#ifndef _di_fll_program_print_help_option_long_ - f_status_t fll_program_print_help_option_long(const f_file_t output, const f_color_context_t context, const f_string_static_t option_long, const f_string_static_t symbol_long, const char *description) { - - fl_print_format("%r %Q%[%Q%] %S", output.stream, f_string_eol_s, symbol_long, context.set.standout, option_long, context.set.standout, description); - - return F_none; - } -#endif // _di_fll_program_print_help_option_long_ - -#ifndef _di_fll_program_print_help_option_other_ - f_status_t fll_program_print_help_option_other(const f_file_t output, const f_color_context_t context, const f_string_static_t option_other, const char *description) { - - fl_print_format("%r %[%Q%] %S", output.stream, f_string_eol_s, context.set.standout, option_other, context.set.standout, description); - - return F_none; - } -#endif // _di_fll_program_print_help_option_other_ - -#ifndef _di_fll_program_print_help_usage_ - f_status_t fll_program_print_help_usage(const f_file_t output, const f_color_context_t context, const f_string_static_t name, const f_string_static_t parameters) { - - fl_print_format("%r%r %[Usage:%]%r", output.stream, f_string_eol_s, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" %[%Q%]", output.stream, context.set.standout, name, context.set.standout); - fl_print_format(" %[[%] options %[]%]", output.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - - if (parameters.used) { - fl_print_format(" %[[%] %Q %[]%]", output.stream, context.set.notable, context.set.notable, parameters, context.set.notable, context.set.notable); - } - - f_print_dynamic_raw(f_string_eol_s, output.stream); - - return F_none; - } -#endif // _di_fll_program_print_help_usage_ - -#ifndef _di_fll_program_print_version_ - f_status_t fll_program_print_version(const f_file_t output, const f_string_static_t version) { - - f_print_dynamic(version, output.stream); - f_print_dynamic_raw(f_string_eol_s, output.stream); - - return F_none; - } -#endif // _di_fll_program_print_version_ - #ifndef _di_fll_program_parameter_process_context_ f_status_t fll_program_parameter_process_context(const f_uint16s_t choices, const uint8_t modes[], const bool right, fll_program_data_t * const main) { @@ -331,15 +246,15 @@ extern "C" { #ifndef _di_fll_program_parameter_long_print_cannot_use_with_ f_status_t fll_program_parameter_long_print_cannot_use_with(const fl_print_t print, const f_string_static_t first, const f_string_static_t second) { - flockfile(print.to.stream); + f_file_stream_lock(print.to); - fl_print_format("%r%[%QCannot specify the '%]", print.to.stream, f_string_eol_s, print.context, print.prefix, print.context); + fl_print_format("%[%QCannot specify the '%]", print.to.stream, print.context, print.prefix, print.context); fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, first, print.notable); fl_print_format("%[' parameter with the '%]", print.to.stream, print.context, print.context); fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, second, print.notable); fl_print_format("%[' parameter.%]%r", print.to.stream, print.context, print.context, f_string_eol_s); - funlockfile(print.to.stream); + f_file_stream_unlock(print.to); return F_none; } diff --git a/level_2/fll_program/c/program.h b/level_2/fll_program/c/program.h index 22a71ce..ccda4f8 100644 --- a/level_2/fll_program/c/program.h +++ b/level_2/fll_program/c/program.h @@ -31,181 +31,13 @@ // FLL-2 program includes. #include +#include #ifdef __cplusplus extern "C" { #endif /** - * Print standard help header. - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param context - * The color context. - * @param name - * The name of the program. - * @param version - * The version number of the program. - * - * @return - * F_none on success. - * - * @see f_print_terminated() - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_help_header_ - extern f_status_t fll_program_print_help_header(const f_file_t output, const f_color_context_t context, const f_string_static_t name, const f_string_static_t version); -#endif // _di_fll_program_print_help_header_ - -/** - * Print standard help option. - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param context - * The color context. - * @param option_short - * The short name of the option. - * @param option_long - * The long name of the option. - * @param symbol_short - * The short symbol of the option. - * @param symbol_long - * The long symbol of the option. - * @param description - * A desciption associated with the option. - * - * @return - * F_none on success. - * - * @see f_print_terminated() - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_help_option_ - extern f_status_t fll_program_print_help_option(const f_file_t output, const f_color_context_t context, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description); -#endif // _di_fll_program_print_help_option_ - -/** - * Print standard help option (long option only). - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param context - * The color context. - * @param option_long - * The long name of the option. - * @param symbol_long - * The long symbol of the option. - * @param description - * A desciption associated with the option. - * - * @return - * F_none on success. - * - * @see f_print_terminated() - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_help_option_long_ - extern f_status_t fll_program_print_help_option_long(const f_file_t output, const f_color_context_t context, const f_string_static_t option_long, const f_string_static_t symbol_long, const char *description); -#endif // _di_fll_program_print_help_option_long_ - -/** - * Print standard help option (other option only). - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param context - * The color context. - * @param option_other - * The other name of the option. - * @param description - * A desciption associated with the option. - * - * @return - * F_none on success. - * - * @see f_print_terminated() - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_help_option_other_ - extern f_status_t fll_program_print_help_option_other(const f_file_t output, const f_color_context_t context, const f_string_static_t option_other, const char *description); -#endif // _di_fll_program_print_help_option_other_ - -/** - * Print all standard help options. - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param context - * The color context. - * - * @return - * F_none on success. - * - * @see f_print_terminated() - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_help_option_standard_ - extern f_status_t fll_program_print_help_option_standard(const f_file_t output, const f_color_context_t context); -#endif // _di_fll_program_print_help_option_standard_ - -/** - * Print standard help usage. - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param context - * The color context. - * @param name - * The name of the program. - * @param parameters - * (optional) The non-option parameters to be displayed inside the brackets. - * Set the first array value to EOS to disable printing of parameters. - * Set parameters.used to 0 to disable. - * - * @return - * F_none on success. - * - * @see f_print_terminated() - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_help_usage_ - extern f_status_t fll_program_print_help_usage(const f_file_t output, const f_color_context_t context, const f_string_static_t name, const f_string_static_t parameters); -#endif // _di_fll_program_print_help_usage_ - -/** - * Print the program version. - * - * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. - * - * @param output - * The file stream to output to. - * @param version - * The version number of the program. - * - * @return - * F_none on success. - * - * @see fl_print_format() - */ -#ifndef _di_fll_program_print_version_ - extern f_status_t fll_program_print_version(const f_file_t output, const f_string_static_t version); -#endif // _di_fll_program_print_version_ - -/** * Determine the color context from the parameters and then set the color context based on the choice. * * This will allow for the color context and the color sets to be safely used when colors are disabled. @@ -501,6 +333,7 @@ extern "C" { * * @param main * The main program data. + * The main->signal must be used to designate blocked signals. * * @return * A positive number representing a valid signal on signal received. diff --git a/level_2/fll_program/c/program/print.c b/level_2/fll_program/c/program/print.c new file mode 100644 index 0000000..285cebb --- /dev/null +++ b/level_2/fll_program/c/program/print.c @@ -0,0 +1,117 @@ +#include "../program.h" +#include "../private-program.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fll_program_print_help_header_ + f_status_t fll_program_print_help_header(const fl_print_t print, const f_string_static_t name, const f_string_static_t version) { + + fl_print_format(" %[%Q%]%r", print.to.stream, print.set->title, name, print.set->title, f_string_eol_s); + fl_print_format(" %[Version %Q%]%r", print.to.stream, print.set->notable, version, print.set->notable, f_string_eol_s); + + fl_print_format("%r %[Available Options:%] ", print.to.stream, f_string_eol_s, print.set->important, print.set->important); + + return F_none; + } +#endif // _di_fll_program_print_help_header_ + +#ifndef _di_fll_program_print_help_option_ + f_status_t fll_program_print_help_option(const fl_print_t print, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description) { + + return private_fll_program_print_help_option(print, option_short, option_long, symbol_short, symbol_long, description); + } +#endif // _di_fll_program_print_help_option_ + +#ifndef _di_fll_program_print_help_option_standard_ + f_status_t fll_program_print_help_option_standard(const fl_print_t print) { + + private_fll_program_print_help_option(print, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message."); + private_fll_program_print_help_option(print, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds."); + private_fll_program_print_help_option(print, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds."); + private_fll_program_print_help_option(print, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Do not print using color."); + private_fll_program_print_help_option(print, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, silencing most print.to."); + private_fll_program_print_help_option(print, f_console_standard_short_error_s, f_console_standard_long_error_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, using only error print.to."); + private_fll_program_print_help_option(print, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal."); + private_fll_program_print_help_option(print, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal print.to."); + private_fll_program_print_help_option(print, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, significantly increasing verbosity beyond normal print.to."); + private_fll_program_print_help_option(print, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number."); + private_fll_program_print_help_option(print, f_console_standard_short_line_first_no_s, f_console_standard_long_line_first_no_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Disable printing of first line."); + private_fll_program_print_help_option(print, f_console_standard_short_line_last_no_s, f_console_standard_long_line_last_no_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Disable printing of last line."); + + return F_none; + } +#endif // _di_fll_program_print_help_option_standard_ + +#ifndef _di_fll_program_print_help_option_long_ + f_status_t fll_program_print_help_option_long(const fl_print_t print, const f_string_static_t option_long, const f_string_static_t symbol_long, const char *description) { + + fl_print_format("%r %Q%[%Q%] %S", print.to.stream, f_string_eol_s, symbol_long, print.set->standout, option_long, print.set->standout, description); + + return F_none; + } +#endif // _di_fll_program_print_help_option_long_ + +#ifndef _di_fll_program_print_help_option_other_ + f_status_t fll_program_print_help_option_other(const fl_print_t print, const f_string_static_t option_other, const char *description) { + + fl_print_format("%r %[%Q%] %S", print.to.stream, f_string_eol_s, print.set->standout, option_other, print.set->standout, description); + + return F_none; + } +#endif // _di_fll_program_print_help_option_other_ + +#ifndef _di_fll_program_print_help_usage_ + f_status_t fll_program_print_help_usage(const fl_print_t print, const f_string_static_t name, const f_string_static_t parameters) { + + fl_print_format("%r%r %[Usage:%]%r", print.to.stream, f_string_eol_s, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" %[%Q%]", print.to.stream, print.set->standout, name, print.set->standout); + fl_print_format(" %[[%] options %[]%]", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + + if (parameters.used) { + fl_print_format(" %[[%] %Q %[]%]", print.to.stream, print.set->notable, print.set->notable, parameters, print.set->notable, print.set->notable); + } + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + return F_none; + } +#endif // _di_fll_program_print_help_usage_ + +#ifndef _di_fll_program_print_signal_received_ + f_status_t fll_program_print_signal_received(const fl_print_t print, const f_string_static_t line_first, const f_status_t signal) { + + if (print.verbosity != f_console_verbosity_verbose_e && print.verbosity != f_console_verbosity_debug_e) { + return F_output_not; + } + + flockfile(print.to.stream); + + // Must flush and reset color because the interrupt may have interrupted the middle of a print function. + f_file_stream_flush(print.to); + + fl_print_format("%]%r%[Received signal code %]", print.to.stream, print.set->reset, line_first, print.set->warning, print.set->warning); + fl_print_format("%[%i%]", print.to.stream, print.set->notable, signal, print.set->notable); + fl_print_format("%[.%]%r", print.to.stream, print.set->warning, print.set->warning, f_string_eol_s); + + funlockfile(print.to.stream); + + return F_none; + } +#endif // _di_fll_program_print_signal_received_ + +#ifndef _di_fll_program_print_version_ + f_status_t fll_program_print_version(const fl_print_t print, const f_string_static_t version) { + + f_print_dynamic(version, print.to.stream); + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + return F_none; + } +#endif // _di_fll_program_print_version_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_2/fll_program/c/program/print.h b/level_2/fll_program/c/program/print.h new file mode 100644 index 0000000..7568fb9 --- /dev/null +++ b/level_2/fll_program/c/program/print.h @@ -0,0 +1,210 @@ +/** + * FLL - Level 2 + * + * Project: Program + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Defines common data to be used for/by project program. + * + * This is auto-included by program.h and should not need to be explicitly included. + */ +#ifndef _FLL_program_print_h +#define _FLL_program_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print standard help header. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param name + * The name of the program. + * @param version + * The version number of the program. + * + * @return + * F_none on success. + * + * @see f_print_terminated() + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_help_header_ + extern f_status_t fll_program_print_help_header(const fl_print_t print, const f_string_static_t name, const f_string_static_t version); +#endif // _di_fll_program_print_help_header_ + +/** + * Print standard help option. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param option_short + * The short name of the option. + * @param option_long + * The long name of the option. + * @param symbol_short + * The short symbol of the option. + * @param symbol_long + * The long symbol of the option. + * @param description + * A desciption associated with the option. + * + * @return + * F_none on success. + * + * @see f_print_terminated() + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_help_option_ + extern f_status_t fll_program_print_help_option(const fl_print_t print, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description); +#endif // _di_fll_program_print_help_option_ + +/** + * Print standard help option (long option only). + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param option_long + * The long name of the option. + * @param symbol_long + * The long symbol of the option. + * @param description + * A desciption associated with the option. + * + * @return + * F_none on success. + * + * @see f_print_terminated() + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_help_option_long_ + extern f_status_t fll_program_print_help_option_long(const fl_print_t print, const f_string_static_t option_long, const f_string_static_t symbol_long, const char *description); +#endif // _di_fll_program_print_help_option_long_ + +/** + * Print standard help option (other option only). + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param option_other + * The other name of the option. + * @param description + * A desciption associated with the option. + * + * @return + * F_none on success. + * + * @see f_print_terminated() + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_help_option_other_ + extern f_status_t fll_program_print_help_option_other(const fl_print_t print, const f_string_static_t option_other, const char *description); +#endif // _di_fll_program_print_help_option_other_ + +/** + * Print all standard help options. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param context + * The color context. + * + * @return + * F_none on success. + * + * @see f_print_terminated() + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_help_option_standard_ + extern f_status_t fll_program_print_help_option_standard(const fl_print_t print); +#endif // _di_fll_program_print_help_option_standard_ + +/** + * Print standard help usage. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param name + * The name of the program. + * @param parameters + * (optional) The non-option parameters to be displayed inside the brackets. + * Set the first array value to EOS to disable printing of parameters. + * Set parameters.used to 0 to disable. + * + * @return + * F_none on success. + * + * @see f_print_terminated() + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_help_usage_ + extern f_status_t fll_program_print_help_usage(const fl_print_t print, const f_string_static_t name, const f_string_static_t parameters); +#endif // _di_fll_program_print_help_usage_ + +/** + * Print a message about a process signal being recieved, such as an interrupt signal, as a warning. + * + * This is only printed when verbosity is set to verbose or debug. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param line_first + * The first line character, which is expected to be set to either f_string_eol_s or f_string_empty_s. + * @param signal + * The signal code received. + * + * @return + * F_none on success. + * F_output_not on success, but no printing is performed. + */ +#ifndef _di_fll_program_print_signal_received_ + extern f_status_t fll_program_print_signal_received(const fl_print_t print, const f_string_static_t line_first, const f_status_t signal); +#endif // _di_fll_program_print_signal_received_ + +/** + * Print the program version. + * + * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called. + * + * @param print + * The output structure to print to. + * This requires print.set to be non-NULL. + * @param version + * The version number of the program. + * + * @return + * F_none on success. + * + * @see fl_print_format() + */ +#ifndef _di_fll_program_print_version_ + extern f_status_t fll_program_print_version(const fl_print_t print, const f_string_static_t version); +#endif // _di_fll_program_print_version_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _FLL_program_print_h diff --git a/level_2/fll_program/data/build/settings b/level_2/fll_program/data/build/settings index 76dcafb..081fa82 100644 --- a/level_2/fll_program/data/build/settings +++ b/level_2/fll_program/data/build/settings @@ -20,9 +20,9 @@ build_language c build_libraries -lc build_libraries-individual -lfl_print -lfl_string -lf_color -lf_console -lf_conversion -lf_file -lf_memory -lf_print -lf_signal -lf_string -lf_type_array -lf_utf -build_sources_library program.c program/common.c private-program.c +build_sources_library program.c program/common.c program/print.c private-program.c -build_sources_headers program.h program/common.h +build_sources_headers program.h program/common.h program/print.h build_script yes build_shared yes diff --git a/level_2/fll_status_string/tests/unit/c/test-status_string-from.c b/level_2/fll_status_string/tests/unit/c/test-status_string-from.c index 529a76a..d23bbd3 100644 --- a/level_2/fll_status_string/tests/unit/c/test-status_string-from.c +++ b/level_2/fll_status_string/tests/unit/c/test-status_string-from.c @@ -278,6 +278,8 @@ void test__fll_status_string_from__works(void **state) { F_no_not, F_object, F_object_not, + F_okay, + F_okay_not, F_once, F_once_not, F_option, @@ -870,6 +872,8 @@ void test__fll_status_string_from__works(void **state) { f_status_no_not_s, f_status_object_s, f_status_object_not_s, + f_status_okay_s, + f_status_okay_not_s, f_status_once_s, f_status_once_not_s, f_status_option_s, @@ -1229,7 +1233,7 @@ void test__fll_status_string_from__works(void **state) { f_status_status_code_last_s, }; - for (uint16_t i = 0; i < 589; ++i) { + for (uint16_t i = 0; i < 591; ++i) { f_status_t result = F_none; diff --git a/level_3/byte_dump/c/byte_dump.c b/level_3/byte_dump/c/byte_dump.c index bbeb216..f23e811 100644 --- a/level_3/byte_dump/c/byte_dump.c +++ b/level_3/byte_dump/c/byte_dump.c @@ -6,79 +6,8 @@ extern "C" { #endif -#ifndef _di_byte_dump_print_help_ - f_status_t byte_dump_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, byte_dump_program_name_long_s, byte_dump_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, byte_dump_short_binary_s, byte_dump_long_binary_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display binary representation."); - fll_program_print_help_option(file, context, byte_dump_short_decimal_s, byte_dump_long_decimal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display decimal representation."); - fll_program_print_help_option(file, context, byte_dump_short_duodecimal_s, byte_dump_long_duodecimal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display duodecimal representation."); - fll_program_print_help_option(file, context, byte_dump_short_hexidecimal_s, byte_dump_long_hexidecimal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Display hexadecimal representation."); - fll_program_print_help_option(file, context, byte_dump_short_octal_s, byte_dump_long_octal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display octal representation."); - fll_program_print_help_option(file, context, byte_dump_short_unicode_s, byte_dump_long_unicode_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display using Unicode representation for valid Unicode (like: U+0000)."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, byte_dump_short_first_s, byte_dump_long_first_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Start reading at this byte offset."); - fll_program_print_help_option(file, context, byte_dump_short_last_s, byte_dump_long_last_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Stop reading at this (inclusive) byte offset."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, byte_dump_short_narrow_s, byte_dump_long_narrow_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use narrow display, resulting in 1*width reducing size of the text columns."); - fll_program_print_help_option(file, context, byte_dump_short_placeholder_s, byte_dump_long_placeholder_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Use a placeholder character instead of a space for placeholders."); - fll_program_print_help_option(file, context, byte_dump_short_text_s, byte_dump_long_text_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include a column of text when displaying the bytes."); - fll_program_print_help_option(file, context, byte_dump_short_wide_s, byte_dump_long_wide_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use wide display, resulting in 2*width allowing for space for wide characters in the text columns."); - fll_program_print_help_option(file, context, byte_dump_short_width_s, byte_dump_long_width_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Set number of columns of Bytes to display."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fl_print_format(" %[Special Options:%] ", file.stream, context.set.important, context.set.important); - - fll_program_print_help_option_long(file, context, byte_dump_long_normal_s, f_console_symbol_long_enable_s, " Display UTF-8 symbols for ASCII control codes."); - fll_program_print_help_option_long(file, context, byte_dump_long_simple_s, f_console_symbol_long_enable_s, " Display spaces for ASCII control codes."); - fll_program_print_help_option_long(file, context, byte_dump_long_classic_s, f_console_symbol_long_enable_s, "Display periods for ASCII control codes."); - - fll_program_print_help_usage(file, context, byte_dump_program_name_s, fll_program_parameter_filenames_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fl_print_format(" When using the %[%r%r%] option, some UTF-8 characters may be replaced by your instance and cause display alignment issues.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_text_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Special UTF-8 characters and non-spacing UTF-8 characters may be replaced with a space (or a placeholder when the %[%r%r%] option is used).%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_placeholder_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" UTF-8 \"Combining\" characters might have a space appended to allow a proper display but this may cause copy and paste issues.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When %[%r%r%] is used, any UTF-8 sequences will still be printed in full should any part is found within the requested range.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_last_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, invalid Unicode will fallback to being displayed using one of the other modes.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_unicode_s, context.set.notable, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_byte_dump_print_help_ - #ifndef _di_byte_dump_main_ - f_status_t byte_dump_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t byte_dump_main(fll_program_data_t * const main, byte_dump_setting_t * const setting) { f_status_t status = F_none; @@ -212,13 +141,13 @@ extern "C" { status = F_none; if (main->parameters.array[byte_dump_parameter_help_e].result == f_console_result_found_e) { - byte_dump_print_help(main->output.to, main->context); + byte_dump_print_help(setting, main->message); return F_none; } if (main->parameters.array[byte_dump_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, byte_dump_program_version_s); + fll_program_print_version(main->message, byte_dump_program_version_s); return F_none; } diff --git a/level_3/byte_dump/c/byte_dump.h b/level_3/byte_dump/c/byte_dump.h index f25b91a..893b430 100644 --- a/level_3/byte_dump/c/byte_dump.h +++ b/level_3/byte_dump/c/byte_dump.h @@ -54,23 +54,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - * - * @see byte_dump_main() - */ -#ifndef _di_byte_dump_print_help_ - extern f_status_t byte_dump_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_byte_dump_print_help_ - -/** * Execute main program. * * @param main @@ -95,9 +78,75 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_byte_dump_main_ - extern f_status_t byte_dump_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t byte_dump_main(fll_program_data_t * const main, byte_dump_setting_t * const setting); #endif // _di_byte_dump_main_ +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_byte_dump_setting_delete_ + extern f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting); +#endif // _di_byte_dump_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_byte_dump_setting_load_ + extern void byte_dump_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, byte_dump_setting_t * const setting); +#endif // _di_byte_dump_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_byte_dump_setting_unload_ + extern f_status_t byte_dump_setting_unload(fll_program_data_t * const main, byte_dump_setting_t * const setting); +#endif // _di_byte_dump_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/byte_dump/c/common.c b/level_3/byte_dump/c/common.c index a9659c7..53e56aa 100644 --- a/level_3/byte_dump/c/common.c +++ b/level_3/byte_dump/c/common.c @@ -67,6 +67,358 @@ extern "C" { const f_string_static_t byte_dump_long_classic_s = macro_f_string_static_t_initialize(BYTE_DUMP_long_classic_s, 0, BYTE_DUMP_long_classic_s_length); #endif // _di_byte_dump_parameters_ +#ifndef _di_byte_dump_setting_delete_ + f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_byte_dump_setting_delete_ + +#ifndef _di_byte_dump_setting_load_ + void byte_dump_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, byte_dump_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { byte_dump_parameter_no_color_e, byte_dump_parameter_light_e, byte_dump_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + byte_dump_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[byte_dump_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[byte_dump_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { byte_dump_parameter_verbosity_quiet_e, byte_dump_parameter_verbosity_error_e, byte_dump_parameter_verbosity_verbose_e, byte_dump_parameter_verbosity_debug_e, byte_dump_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + byte_dump_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[byte_dump_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= byte_dump_main_flag_help_e; + + return; + } + + if (main->parameters.array[byte_dump_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= byte_dump_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { byte_dump_parameter_from_bytesequence_e, byte_dump_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + byte_dump_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == byte_dump_parameter_from_bytesequence_e) { + if (setting->mode & byte_dump_mode_from_codepoint_e) { + setting->mode -= byte_dump_mode_from_codepoint_e; + } + + setting->mode |= byte_dump_mode_from_bytesequence_e; + } + else if (choices.array[choice] == byte_dump_parameter_from_codepoint_e) { + if (setting->mode & byte_dump_mode_from_bytesequence_e) { + setting->mode -= byte_dump_mode_from_bytesequence_e; + } + + setting->mode |= byte_dump_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { byte_dump_parameter_to_bytesequence_e, byte_dump_parameter_to_codepoint_e, byte_dump_parameter_to_combining_e, byte_dump_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + byte_dump_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == byte_dump_parameter_to_bytesequence_e) { + if (setting->mode & byte_dump_mode_to_codepoint_e) { + setting->mode -= byte_dump_mode_to_codepoint_e; + } + + if (setting->mode & byte_dump_mode_to_combining_e) { + setting->mode -= byte_dump_mode_to_combining_e; + } + + if (setting->mode & byte_dump_mode_to_width_e) { + setting->mode -= byte_dump_mode_to_width_e; + } + + setting->mode |= byte_dump_mode_to_bytesequence_e; + } + else if (choices.array[choice] == byte_dump_parameter_to_codepoint_e) { + if (setting->mode & byte_dump_mode_to_bytesequence_e) { + setting->mode -= byte_dump_mode_to_bytesequence_e; + } + + if (setting->mode & byte_dump_mode_to_combining_e) { + setting->mode -= byte_dump_mode_to_combining_e; + } + + if (setting->mode & byte_dump_mode_to_width_e) { + setting->mode -= byte_dump_mode_to_width_e; + } + + setting->mode |= byte_dump_mode_to_codepoint_e; + } + else if (choices.array[choice] == byte_dump_parameter_to_combining_e) { + if (setting->mode & byte_dump_mode_to_bytesequence_e) { + setting->mode -= byte_dump_mode_to_bytesequence_e; + } + + if (setting->mode & byte_dump_mode_to_codepoint_e) { + setting->mode -= byte_dump_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[byte_dump_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= byte_dump_mode_to_width_e; + } + + setting->mode |= byte_dump_mode_to_combining_e; + } + else if (choices.array[choice] == byte_dump_parameter_to_width_e) { + if (setting->mode & byte_dump_mode_to_bytesequence_e) { + setting->mode -= byte_dump_mode_to_bytesequence_e; + } + + if (setting->mode & byte_dump_mode_to_codepoint_e) { + setting->mode -= byte_dump_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[byte_dump_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= byte_dump_mode_to_combining_e; + } + + setting->mode |= byte_dump_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[byte_dump_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[byte_dump_parameter_to_file_e].values.used > 1) { + byte_dump_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[byte_dump_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[byte_dump_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[byte_dump_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[byte_dump_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= byte_dump_main_flag_file_to_e; + } + else { + byte_dump_print_error_parameter_file_name_empty(main, setting, main->parameters.array[byte_dump_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[byte_dump_parameter_to_file_e].result == f_console_result_found_e) { + byte_dump_print_error_no_value(main, setting, byte_dump_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & byte_dump_main_flag_file_to_e) { + setting->flag -= byte_dump_main_flag_file_to_e; + } + } + + if (main->parameters.array[byte_dump_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[byte_dump_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[byte_dump_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[byte_dump_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + byte_dump_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + byte_dump_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= byte_dump_main_flag_file_from_e; + } + else if (main->parameters.array[byte_dump_parameter_from_file_e].result == f_console_result_found_e) { + byte_dump_print_error_no_value(main, setting, byte_dump_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & byte_dump_main_flag_file_from_e) { + setting->flag -= byte_dump_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[byte_dump_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + byte_dump_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & byte_dump_mode_to_bytesequence_e)) { + if (main->parameters.array[byte_dump_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[byte_dump_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = byte_dump_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[byte_dump_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= byte_dump_main_flag_header_e; + } + + if (main->parameters.array[byte_dump_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= byte_dump_main_flag_separate_e; + } + + if (main->parameters.array[byte_dump_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= byte_dump_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_byte_dump_setting_load_ + +#ifndef _di_byte_dump_setting_unload_ + f_status_t byte_dump_setting_unload(fll_program_data_t * const main, byte_dump_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + byte_dump_setting_delete(setting); + + return F_none; + } +#endif // _di_byte_dump_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/byte_dump/c/common.h b/level_3/byte_dump/c/common.h index 17e88a9..df5c7ec 100644 --- a/level_3/byte_dump/c/common.h +++ b/level_3/byte_dump/c/common.h @@ -343,6 +343,66 @@ extern "C" { #define byte_dump_total_parameters_d 28 #endif // _di_byte_dump_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * byte_dump_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_byte_dump_main_flag_e_ + enum { + byte_dump_main_flag_none_e = 0x0, + byte_dump_main_flag_file_from_e = 0x1, + byte_dump_main_flag_file_to_e = 0x2, + byte_dump_main_flag_header_e = 0x4, + byte_dump_main_flag_help_e = 0x8, + byte_dump_main_flag_separate_e = 0x10, + byte_dump_main_flag_strip_invalid_e = 0x20, + byte_dump_main_flag_verify_e = 0x40, + byte_dump_main_flag_version_e = 0x80, + }; +#endif // _di_byte_dump_main_flag_e_ + +/** + * The byte dump main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_byte_dump_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } byte_dump_setting_t; + + #define byte_dump_setting_t_initialize \ + { \ + byte_dump_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_byte_dump_setting_t_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/byte_dump/c/main.c b/level_3/byte_dump/c/main.c index f05e1b0..d32ca7f 100644 --- a/level_3/byte_dump/c/main.c +++ b/level_3/byte_dump/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + byte_dump_setting_t setting = byte_dump_setting_t_initialize; f_console_parameter_t parameters[] = byte_dump_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = byte_dump_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = byte_dump_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + byte_dump_setting_load(arguments, &data, &setting); + } + + byte_dump_main(&data, &setting); + + byte_dump_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/byte_dump/c/print.c b/level_3/byte_dump/c/print.c new file mode 100644 index 0000000..da007da --- /dev/null +++ b/level_3/byte_dump/c/print.c @@ -0,0 +1,108 @@ +#include "byte_dump.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_byte_dump_print_help_ + f_status_t byte_dump_print_help(byte_dump_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, byte_dump_program_name_long_s, byte_dump_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, byte_dump_short_binary_s, byte_dump_long_binary_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display binary representation."); + fll_program_print_help_option(print, byte_dump_short_decimal_s, byte_dump_long_decimal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display decimal representation."); + fll_program_print_help_option(print, byte_dump_short_duodecimal_s, byte_dump_long_duodecimal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display duodecimal representation."); + fll_program_print_help_option(print, byte_dump_short_hexidecimal_s, byte_dump_long_hexidecimal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Display hexadecimal representation."); + fll_program_print_help_option(print, byte_dump_short_octal_s, byte_dump_long_octal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display octal representation."); + fll_program_print_help_option(print, byte_dump_short_unicode_s, byte_dump_long_unicode_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Display using Unicode representation for valid Unicode (like: U+0000)."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, byte_dump_short_first_s, byte_dump_long_first_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Start reading at this byte offset."); + fll_program_print_help_option(print, byte_dump_short_last_s, byte_dump_long_last_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Stop reading at this (inclusive) byte offset."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, byte_dump_short_narrow_s, byte_dump_long_narrow_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use narrow display, resulting in 1*width reducing size of the text columns."); + fll_program_print_help_option(print, byte_dump_short_placeholder_s, byte_dump_long_placeholder_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Use a placeholder character instead of a space for placeholders."); + fll_program_print_help_option(print, byte_dump_short_text_s, byte_dump_long_text_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include a column of text when displaying the bytes."); + fll_program_print_help_option(print, byte_dump_short_wide_s, byte_dump_long_wide_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use wide display, resulting in 2*width allowing for space for wide characters in the text columns."); + fll_program_print_help_option(print, byte_dump_short_width_s, byte_dump_long_width_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Set number of columns of Bytes to display."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fl_print_format(" %[Special Options:%] ", print.to.stream, context.set.important, context.set.important); + + fll_program_print_help_option_long(print.to, context, byte_dump_long_normal_s, f_console_symbol_long_enable_s, " Display UTF-8 symbols for ASCII control codes."); + fll_program_print_help_option_long(print.to, context, byte_dump_long_simple_s, f_console_symbol_long_enable_s, " Display spaces for ASCII control codes."); + fll_program_print_help_option_long(print.to, context, byte_dump_long_classic_s, f_console_symbol_long_enable_s, "Display periods for ASCII control codes."); + + fll_program_print_help_usage(print, byte_dump_program_name_s, fll_program_parameter_filenames_s); + + //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + //} + + fl_print_format(" When using the %[%r%r%] option, some UTF-8 characters may be replaced by your instance and cause display alignment issues.%r%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_text_s, context.set.notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Special UTF-8 characters and non-spacing UTF-8 characters may be replaced with a space (or a placeholder when the %[%r%r%] option is used).%r%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_placeholder_s, context.set.notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" UTF-8 \"Combining\" characters might have a space appended to allow a proper display but this may cause copy and paste issues.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When %[%r%r%] is used, any UTF-8 sequences will still be printed in full should any part is found within the requested range.%r%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_last_s, context.set.notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, invalid Unicode will fallback to being displayed using one of the other modes.%r", print.to.stream, context.set.notable, f_console_symbol_long_enable_s, byte_dump_long_unicode_s, context.set.notable, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(output); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_byte_dump_print_help_ + +#ifndef _di_byte_dump_print_line_first_ + void byte_dump_print_line_first(byte_dump_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_byte_dump_print_line_first_ + +#ifndef _di_byte_dump_print_line_last_ + void byte_dump_print_line_last(byte_dump_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & byte_dump_main_flag_verify_e) return; + if ((setting->flag & byte_dump_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_byte_dump_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/byte_dump/c/print.h b/level_3/byte_dump/c/print.h new file mode 100644 index 0000000..311a6a3 --- /dev/null +++ b/level_3/byte_dump/c/print.h @@ -0,0 +1,75 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _byte_dump_print_h +#define _byte_dump_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param output + * The file to print to. + * @param context + * The color context settings. + * + * @return + * F_none on success. + * + * @see byte_dump_main() + */ +#ifndef _di_byte_dump_print_help_ + extern f_status_t byte_dump_print_help(byte_dump_setting_t * const setting, const fl_print_t print); +#endif // _di_byte_dump_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_byte_dump_print_line_first_ + extern void byte_dump_print_line_first(byte_dump_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_byte_dump_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_byte_dump_print_line_last_ + extern void byte_dump_print_line_last(byte_dump_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_byte_dump_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _byte_dump_print_h diff --git a/level_3/byte_dump/c/private-byte_dump.c b/level_3/byte_dump/c/private-byte_dump.c index 2d94f96..d72dac8 100644 --- a/level_3/byte_dump/c/private-byte_dump.c +++ b/level_3/byte_dump/c/private-byte_dump.c @@ -60,7 +60,7 @@ extern "C" { if (!((++data->main->signal_check) % byte_dump_signal_check_d)) { if (fll_program_standard_signal_received(data->main)) { - byte_dump_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/byte_dump/c/private-common.c b/level_3/byte_dump/c/private-common.c index 54d8b21..820be90 100644 --- a/level_3/byte_dump/c/private-common.c +++ b/level_3/byte_dump/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_byte_dump_print_signal_received_ - void byte_dump_print_signal_received(byte_dump_data_t * const data) { - - if (data->main->warning.verbosity != f_console_verbosity_verbose_e && data->main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(data->main->warning.to.stream); - - flockfile(data->main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", data->main->warning.to.stream, data->main->context.set.reset, f_string_eol_s, f_string_eol_s, data->main->context.set.warning, data->main->context.set.warning); - fl_print_format("%[%i%]", data->main->warning.to.stream, data->main->context.set.notable, data->main->signal_received, data->main->context.set.notable); - fl_print_format("%[.%]%r", data->main->warning.to.stream, data->main->context.set.warning, data->main->context.set.warning, f_string_eol_s); - - funlockfile(data->main->warning.to.stream); - } -#endif // _di_byte_dump_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/byte_dump/c/private-common.h b/level_3/byte_dump/c/private-common.h index de72bec..12c01cb 100644 --- a/level_3/byte_dump/c/private-common.h +++ b/level_3/byte_dump/c/private-common.h @@ -93,16 +93,6 @@ extern "C" { } #endif // _di_byte_previous_cell_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_byte_dump_print_signal_received_ - extern void byte_dump_print_signal_received(byte_dump_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_byte_dump_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/byte_dump/data/build/settings b/level_3/byte_dump/data/build/settings index 348b338..ce543f9 100644 --- a/level_3/byte_dump/data/build/settings +++ b/level_3/byte_dump/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library byte_dump.c common.c private-common.c private-byte_dump.c +build_sources_library byte_dump.c common.c print.c private-common.c private-byte_dump.c build_sources_program main.c -build_sources_headers byte_dump.h common.h +build_sources_headers byte_dump.h common.h print.h build_script yes build_shared yes diff --git a/level_3/control/c/common.c b/level_3/control/c/common.c index 846c3d5..550fde8 100644 --- a/level_3/control/c/common.c +++ b/level_3/control/c/common.c @@ -170,6 +170,358 @@ extern "C" { } #endif // _di_control_payload_type_name_ +#ifndef _di_control_setting_delete_ + f_status_t control_setting_delete(control_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_control_setting_delete_ + +#ifndef _di_control_setting_load_ + void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { control_parameter_no_color_e, control_parameter_light_e, control_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + control_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[control_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[control_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { control_parameter_verbosity_quiet_e, control_parameter_verbosity_error_e, control_parameter_verbosity_verbose_e, control_parameter_verbosity_debug_e, control_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + control_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[control_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= control_main_flag_help_e; + + return; + } + + if (main->parameters.array[control_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= control_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { control_parameter_from_bytesequence_e, control_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + control_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == control_parameter_from_bytesequence_e) { + if (setting->mode & control_mode_from_codepoint_e) { + setting->mode -= control_mode_from_codepoint_e; + } + + setting->mode |= control_mode_from_bytesequence_e; + } + else if (choices.array[choice] == control_parameter_from_codepoint_e) { + if (setting->mode & control_mode_from_bytesequence_e) { + setting->mode -= control_mode_from_bytesequence_e; + } + + setting->mode |= control_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { control_parameter_to_bytesequence_e, control_parameter_to_codepoint_e, control_parameter_to_combining_e, control_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + control_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == control_parameter_to_bytesequence_e) { + if (setting->mode & control_mode_to_codepoint_e) { + setting->mode -= control_mode_to_codepoint_e; + } + + if (setting->mode & control_mode_to_combining_e) { + setting->mode -= control_mode_to_combining_e; + } + + if (setting->mode & control_mode_to_width_e) { + setting->mode -= control_mode_to_width_e; + } + + setting->mode |= control_mode_to_bytesequence_e; + } + else if (choices.array[choice] == control_parameter_to_codepoint_e) { + if (setting->mode & control_mode_to_bytesequence_e) { + setting->mode -= control_mode_to_bytesequence_e; + } + + if (setting->mode & control_mode_to_combining_e) { + setting->mode -= control_mode_to_combining_e; + } + + if (setting->mode & control_mode_to_width_e) { + setting->mode -= control_mode_to_width_e; + } + + setting->mode |= control_mode_to_codepoint_e; + } + else if (choices.array[choice] == control_parameter_to_combining_e) { + if (setting->mode & control_mode_to_bytesequence_e) { + setting->mode -= control_mode_to_bytesequence_e; + } + + if (setting->mode & control_mode_to_codepoint_e) { + setting->mode -= control_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[control_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= control_mode_to_width_e; + } + + setting->mode |= control_mode_to_combining_e; + } + else if (choices.array[choice] == control_parameter_to_width_e) { + if (setting->mode & control_mode_to_bytesequence_e) { + setting->mode -= control_mode_to_bytesequence_e; + } + + if (setting->mode & control_mode_to_codepoint_e) { + setting->mode -= control_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[control_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= control_mode_to_combining_e; + } + + setting->mode |= control_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[control_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[control_parameter_to_file_e].values.used > 1) { + control_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[control_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[control_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[control_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[control_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= control_main_flag_file_to_e; + } + else { + control_print_error_parameter_file_name_empty(main, setting, main->parameters.array[control_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[control_parameter_to_file_e].result == f_console_result_found_e) { + control_print_error_no_value(main, setting, control_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & control_main_flag_file_to_e) { + setting->flag -= control_main_flag_file_to_e; + } + } + + if (main->parameters.array[control_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[control_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[control_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[control_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + control_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + control_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= control_main_flag_file_from_e; + } + else if (main->parameters.array[control_parameter_from_file_e].result == f_console_result_found_e) { + control_print_error_no_value(main, setting, control_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & control_main_flag_file_from_e) { + setting->flag -= control_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[control_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + control_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & control_mode_to_bytesequence_e)) { + if (main->parameters.array[control_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[control_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = control_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[control_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= control_main_flag_header_e; + } + + if (main->parameters.array[control_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= control_main_flag_separate_e; + } + + if (main->parameters.array[control_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= control_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_control_setting_load_ + +#ifndef _di_control_setting_unload_ + f_status_t control_setting_unload(fll_program_data_t * const main, control_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + control_setting_delete(setting); + + return F_none; + } +#endif // _di_control_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/control/c/common.h b/level_3/control/c/common.h index 1e77a7d..3712dfe 100644 --- a/level_3/control/c/common.h +++ b/level_3/control/c/common.h @@ -188,6 +188,66 @@ extern "C" { #endif // _di_control_payload_types_ /** + * Flags used to represent flags passed to the main function. + * + * control_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_control_main_flag_e_ + enum { + control_main_flag_none_e = 0x0, + control_main_flag_file_from_e = 0x1, + control_main_flag_file_to_e = 0x2, + control_main_flag_header_e = 0x4, + control_main_flag_help_e = 0x8, + control_main_flag_separate_e = 0x10, + control_main_flag_strip_invalid_e = 0x20, + control_main_flag_verify_e = 0x40, + control_main_flag_version_e = 0x80, + }; +#endif // _di_control_main_flag_e_ + +/** + * The control main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_control_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } control_setting_t; + + #define control_setting_t_initialize \ + { \ + control_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_control_setting_t_ + +/** * Identify the action code the given name represents. * * @param action @@ -243,6 +303,72 @@ extern "C" { extern f_string_static_t control_payload_type_name(const uint8_t type); #endif // _di_control_payload_type_name_ +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_control_setting_delete_ + extern f_status_t control_setting_delete(control_setting_t * const setting); +#endif // _di_control_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_control_setting_load_ + extern void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting); +#endif // _di_control_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_control_setting_unload_ + extern f_status_t control_setting_unload(fll_program_data_t * const main, control_setting_t * const setting); +#endif // _di_control_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/control/c/control.c b/level_3/control/c/control.c index 91c9c21..4c2864b 100644 --- a/level_3/control/c/control.c +++ b/level_3/control/c/control.c @@ -7,52 +7,8 @@ extern "C" { #endif -#ifndef _di_control_print_help_ - f_status_t control_print_help(const fll_program_data_t * const main) { - - flockfile(main->output.to.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(main->output.to, main->context, control_program_name_long_s, control_program_version_s); - - fll_program_print_help_option_standard(main->output.to, context); - - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - - fll_program_print_help_option(main->output.to, main->context, control_short_name_s, control_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify the name of the controller socket file."); - fll_program_print_help_option(main->output.to, main->context, control_short_return_s, control_long_return_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print a message about the response packet."); - fll_program_print_help_option(main->output.to, main->context, control_short_settings_s, control_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Specify a directory path or a full path to the control settings file."); - fll_program_print_help_option(main->output.to, main->context, control_short_socket_s, control_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a directory path or a full path to the controller socket file."); - - fll_program_print_help_usage(main->output.to, main->context, control_program_name_s, control_action_s); - - fl_print_format("%r When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", main->output.to.stream, f_string_eol_s, main->context.set.notable, f_console_symbol_long_enable_s, control_long_socket_s, main->context.set.notable); - fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_name_s, main->context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" A rule action allows for either the full rule path, such as '%[boot/root%]'", main->output.to.stream, main->context.set.notable, main->context.set.notable); - fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", main->output.to.stream, main->context.set.notable, main->context.set.notable); - fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", main->output.to.stream, main->context.set.notable, main->context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, control_long_return_s, main->context.set.notable, f_string_eol_s); - fl_print_format(" Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_disable_s, f_console_standard_long_quiet_s, main->context.set.notable, f_string_eol_s); - fl_print_format(" No response is returned on program errors, especially those errors that prevent communicating to the controller.%r", main->output.to.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - //} - - f_file_stream_flush(main->output.to.stream); - funlockfile(main->output.to.stream); - - return F_none; - } -#endif // _di_control_print_help_ - #ifndef _di_control_main_ - f_status_t control_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting) { f_status_t status = F_none; @@ -108,7 +64,7 @@ extern "C" { } if (main->parameters.array[control_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, control_program_version_s); + fll_program_print_version(main->message, control_program_version_s); return F_none; } diff --git a/level_3/control/c/control.h b/level_3/control/c/control.h index a1f387d..980be6c 100644 --- a/level_3/control/c/control.h +++ b/level_3/control/c/control.h @@ -58,21 +58,6 @@ extern "C" { #endif /** - * Print help. - * - * @param main - * The main program data. - * - * @return - * F_none on success. - * - * @see control_main() - */ -#ifndef _di_control_print_help_ - extern f_status_t control_print_help(const fll_program_data_t * const main); -#endif // _di_control_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -96,7 +81,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_control_main_ - extern f_status_t control_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting); #endif // _di_control_main_ #ifdef __cplusplus diff --git a/level_3/control/c/main.c b/level_3/control/c/main.c index 4c909ac..910a490 100644 --- a/level_3/control/c/main.c +++ b/level_3/control/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + control_setting_t setting = control_setting_t_initialize; f_console_parameter_t parameters[] = control_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = control_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = control_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + control_setting_load(arguments, &data, &setting); + } + + control_main(&data, &setting); + + control_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/control/c/print.c b/level_3/control/c/print.c new file mode 100644 index 0000000..66872e5 --- /dev/null +++ b/level_3/control/c/print.c @@ -0,0 +1,81 @@ +#include "control.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_control_print_help_ + f_status_t control_print_help(control_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, control_program_name_long_s, control_program_version_s); + + fll_program_print_help_option_standard(main->output.to, context); + + f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + + fll_program_print_help_option(print, control_short_name_s, control_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify the name of the controller socket file."); + fll_program_print_help_option(print, control_short_return_s, control_long_return_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print a message about the response packet."); + fll_program_print_help_option(print, control_short_settings_s, control_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Specify a directory path or a full path to the control settings file."); + fll_program_print_help_option(print, control_short_socket_s, control_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a directory path or a full path to the controller socket file."); + + fll_program_print_help_usage(print, control_program_name_s, control_action_s); + + fl_print_format("%r When the %[%r%r%] parameter represents a directory path then the file name is generated from either the", print.to.stream, f_string_eol_s, print.set->notable, f_console_symbol_long_enable_s, control_long_socket_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter or from the control settings file.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, control_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" A rule action allows for either the full rule path, such as '%[boot/root%]'", print.to.stream, print.set->notable, print.set->notable); + fl_print_format(" as a single parameter or two parameters with the first representing the rule directory path '%[boot%]'", print.to.stream, print.set->notable, print.set->notable); + fl_print_format(" and the second representing the rule base name '%[root%]'.%r%r", print.to.stream, print.set->notable, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter is intended to be used for scripting and is of the form \"response [type] [action] [status]\".%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, control_long_return_s, print.set->notable, f_string_eol_s); + fl_print_format(" Be sure to use the %[%r%r%] parameter to suppress output when using this in scripting.%r", print.to.stream, print.set->notable, f_console_symbol_long_disable_s, f_console_standard_long_quiet_s, print.set->notable, f_string_eol_s); + fl_print_format(" No response is returned on program errors, especially those errors that prevent communicating to the controller.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_control_print_help_ + +#ifndef _di_control_print_line_first_ + void control_print_line_first(control_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_control_print_line_first_ + +#ifndef _di_control_print_line_last_ + void control_print_line_last(control_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & control_main_flag_verify_e) return; + if ((setting->flag & control_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_control_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/control/c/print.h b/level_3/control/c/print.h new file mode 100644 index 0000000..d0fbdea --- /dev/null +++ b/level_3/control/c/print.h @@ -0,0 +1,70 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _control_print_h +#define _control_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param main + * The main program data. + * + * @return + * F_none on success. + * + * @see control_main() + */ +#ifndef _di_control_print_help_ + extern f_status_t control_print_help(const fll_program_data_t * const main); +#endif // _di_control_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_control_print_line_first_ + extern void control_print_line_first(control_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_control_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_control_print_line_last_ + extern void control_print_line_last(control_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_control_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _control_print_h diff --git a/level_3/control/c/private-print.c b/level_3/control/c/private-print.c index 4963f40..8fdfaef 100644 --- a/level_3/control/c/private-print.c +++ b/level_3/control/c/private-print.c @@ -407,24 +407,6 @@ extern "C" { } #endif // _di_control_print_error_socket_file_not_ -#ifndef _di_control_print_signal_received_ - void control_print_signal_received(const fll_program_data_t * const main, const f_status_t signal) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code%] ", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_control_print_signal_received_ - #ifndef _di_control_print_warning_packet_header_duplicate_object_ void control_print_warning_packet_header_duplicate_object(const fll_program_data_t * const main, const f_string_static_t response_header) { diff --git a/level_3/control/c/private-print.h b/level_3/control/c/private-print.h index 3241e2e..d136ec1 100644 --- a/level_3/control/c/private-print.h +++ b/level_3/control/c/private-print.h @@ -309,18 +309,6 @@ extern "C" { #endif // _di_control_print_error_socket_file_not_ /** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - * @param signal - * The signal received. - */ -#ifndef _di_control_print_signal_received_ - extern void control_print_signal_received(const fll_program_data_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; -#endif // _di_control_print_signal_received_ - -/** * Print a warning message about a response header being repeated (when debugging). * * This program currently does not support multiple headers for any given valid header Object. diff --git a/level_3/control/data/build/settings b/level_3/control/data/build/settings index 39ea2d1..f5f42a5 100644 --- a/level_3/control/data/build/settings +++ b/level_3/control/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfll build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library control.c common.c private-common.c private-control.c private-print.c +build_sources_library control.c common.c print.c private-common.c private-control.c private-print.c build_sources_program main.c -build_sources_headers control.h common.h +build_sources_headers control.h common.h print.h build_script yes build_shared yes diff --git a/level_3/controller/c/common.c b/level_3/controller/c/common.c index 3d4d102..c73b693 100644 --- a/level_3/controller/c/common.c +++ b/level_3/controller/c/common.c @@ -602,6 +602,358 @@ extern "C" { } #endif // _di_controller_rule_setting_limit_type_name_ +#ifndef _di_controller_setting_delete_ + f_status_t controller_setting_delete(controller_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_controller_setting_delete_ + +#ifndef _di_controller_setting_load_ + void controller_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, controller_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { controller_parameter_no_color_e, controller_parameter_light_e, controller_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + controller_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[controller_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[controller_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { controller_parameter_verbosity_quiet_e, controller_parameter_verbosity_error_e, controller_parameter_verbosity_verbose_e, controller_parameter_verbosity_debug_e, controller_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + controller_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[controller_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= controller_main_flag_help_e; + + return; + } + + if (main->parameters.array[controller_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= controller_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { controller_parameter_from_bytesequence_e, controller_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + controller_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == controller_parameter_from_bytesequence_e) { + if (setting->mode & controller_mode_from_codepoint_e) { + setting->mode -= controller_mode_from_codepoint_e; + } + + setting->mode |= controller_mode_from_bytesequence_e; + } + else if (choices.array[choice] == controller_parameter_from_codepoint_e) { + if (setting->mode & controller_mode_from_bytesequence_e) { + setting->mode -= controller_mode_from_bytesequence_e; + } + + setting->mode |= controller_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { controller_parameter_to_bytesequence_e, controller_parameter_to_codepoint_e, controller_parameter_to_combining_e, controller_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + controller_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == controller_parameter_to_bytesequence_e) { + if (setting->mode & controller_mode_to_codepoint_e) { + setting->mode -= controller_mode_to_codepoint_e; + } + + if (setting->mode & controller_mode_to_combining_e) { + setting->mode -= controller_mode_to_combining_e; + } + + if (setting->mode & controller_mode_to_width_e) { + setting->mode -= controller_mode_to_width_e; + } + + setting->mode |= controller_mode_to_bytesequence_e; + } + else if (choices.array[choice] == controller_parameter_to_codepoint_e) { + if (setting->mode & controller_mode_to_bytesequence_e) { + setting->mode -= controller_mode_to_bytesequence_e; + } + + if (setting->mode & controller_mode_to_combining_e) { + setting->mode -= controller_mode_to_combining_e; + } + + if (setting->mode & controller_mode_to_width_e) { + setting->mode -= controller_mode_to_width_e; + } + + setting->mode |= controller_mode_to_codepoint_e; + } + else if (choices.array[choice] == controller_parameter_to_combining_e) { + if (setting->mode & controller_mode_to_bytesequence_e) { + setting->mode -= controller_mode_to_bytesequence_e; + } + + if (setting->mode & controller_mode_to_codepoint_e) { + setting->mode -= controller_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[controller_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= controller_mode_to_width_e; + } + + setting->mode |= controller_mode_to_combining_e; + } + else if (choices.array[choice] == controller_parameter_to_width_e) { + if (setting->mode & controller_mode_to_bytesequence_e) { + setting->mode -= controller_mode_to_bytesequence_e; + } + + if (setting->mode & controller_mode_to_codepoint_e) { + setting->mode -= controller_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[controller_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= controller_mode_to_combining_e; + } + + setting->mode |= controller_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[controller_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[controller_parameter_to_file_e].values.used > 1) { + controller_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[controller_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[controller_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[controller_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[controller_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= controller_main_flag_file_to_e; + } + else { + controller_print_error_parameter_file_name_empty(main, setting, main->parameters.array[controller_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[controller_parameter_to_file_e].result == f_console_result_found_e) { + controller_print_error_no_value(main, setting, controller_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & controller_main_flag_file_to_e) { + setting->flag -= controller_main_flag_file_to_e; + } + } + + if (main->parameters.array[controller_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[controller_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[controller_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[controller_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + controller_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + controller_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= controller_main_flag_file_from_e; + } + else if (main->parameters.array[controller_parameter_from_file_e].result == f_console_result_found_e) { + controller_print_error_no_value(main, setting, controller_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & controller_main_flag_file_from_e) { + setting->flag -= controller_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[controller_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + controller_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & controller_mode_to_bytesequence_e)) { + if (main->parameters.array[controller_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[controller_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = controller_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[controller_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= controller_main_flag_header_e; + } + + if (main->parameters.array[controller_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= controller_main_flag_separate_e; + } + + if (main->parameters.array[controller_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= controller_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_controller_setting_load_ + +#ifndef _di_controller_setting_unload_ + f_status_t controller_setting_unload(fll_program_data_t * const main, controller_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + controller_setting_delete(setting); + + return F_none; + } +#endif // _di_controller_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/common.h b/level_3/controller/c/common.h index be9d88c..bd62ff9 100644 --- a/level_3/controller/c/common.h +++ b/level_3/controller/c/common.h @@ -446,6 +446,66 @@ extern "C" { #endif // _di_controller_resource_limit_t_ /** + * Flags used to represent flags passed to the main function. + * + * controller_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_controller_main_flag_e_ + enum { + controller_main_flag_none_e = 0x0, + controller_main_flag_file_from_e = 0x1, + controller_main_flag_file_to_e = 0x2, + controller_main_flag_header_e = 0x4, + controller_main_flag_help_e = 0x8, + controller_main_flag_separate_e = 0x10, + controller_main_flag_strip_invalid_e = 0x20, + controller_main_flag_verify_e = 0x40, + controller_main_flag_version_e = 0x80, + }; +#endif // _di_controller_main_flag_e_ + +/** + * The controller main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_controller_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } controller_setting_t; + + #define controller_setting_t_initialize \ + { \ + controller_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_controller_setting_t_ + +/** * Identify the payload code the given name represents. * * @param payload @@ -636,6 +696,72 @@ extern "C" { extern f_string_static_t controller_rule_setting_limit_type_name(const uint8_t type); #endif // di_controller_rule_setting_limit_type_name_ +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_controller_setting_delete_ + extern f_status_t controller_setting_delete(controller_setting_t * const setting); +#endif // _di_controller_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_controller_setting_load_ + extern void controller_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, controller_setting_t * const setting); +#endif // _di_controller_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_controller_setting_unload_ + extern f_status_t controller_setting_unload(fll_program_data_t * const main, controller_setting_t * const setting); +#endif // _di_controller_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/controller.c b/level_3/controller/c/controller.c index 8c3daf3..595d63f 100644 --- a/level_3/controller/c/controller.c +++ b/level_3/controller/c/controller.c @@ -12,53 +12,6 @@ extern "C" { #endif -#ifndef _di_controller_print_help_ - f_status_t controller_print_help(controller_main_t * const main) { - - controller_lock_print(main->output.to, 0); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(main->output.to, main->context, *main->program_name_long, controller_program_version_s); - - fll_program_print_help_option_standard(main->output.to, context); - - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - - fll_program_print_help_option(main->output.to, main->context, controller_short_cgroup_s, controller_long_cgroup_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom control group file path, such as '" F_control_group_path_system_prefix_s F_control_group_path_system_default_s "'."); - fll_program_print_help_option(main->output.to, main->context, controller_short_daemon_s, controller_long_daemon_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run in daemon only mode (do not process the entry)."); - fll_program_print_help_option(main->output.to, main->context, controller_short_init_s, controller_long_init_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The program will run as an init replacement."); - fll_program_print_help_option(main->output.to, main->context, controller_short_interruptible_s, controller_long_interruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate that this program can be interrupted by a signal."); - fll_program_print_help_option(main->output.to, main->context, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom pid file path, such as 'controller/run/default.pid'."); - fll_program_print_help_option(main->output.to, main->context, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom settings path, such as 'controller/'."); - fll_program_print_help_option(main->output.to, main->context, controller_short_simulate_s, controller_long_simulate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run as a simulation."); - fll_program_print_help_option(main->output.to, main->context, controller_short_socket_s, controller_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom socket file path, such as 'controller/run/default.socket'."); - fll_program_print_help_option(main->output.to, main->context, controller_short_uninterruptible_s, controller_long_uninterruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Designate that this program cannot be interrupted by a signal."); - fll_program_print_help_option(main->output.to, main->context, controller_short_validate_s, controller_long_validate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Validate the settings (entry and rules) without running (does not simulate)."); - - fll_program_print_help_usage(main->output.to, main->context, *main->program_name, controller_entry_s); - - fl_print_format("%r When both the %[%r%r%] parameter and the", main->output.to.stream, f_string_eol_s, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_simulate_s, main->context.set.notable); - fl_print_format(" %[%r%r%] parameter are specified, then additional information on each would be executed rule is printed but no simulation is performed.%r%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_validate_s, main->context.set.notable, f_string_eol_s, f_string_eol_s); - - const f_string_static_t interruptable = main->as_init ? controller_long_uninterruptible_s : controller_long_interruptible_s; - - fl_print_format(" The default interrupt behavior is to operate as if the %[%r%r%] parameter is passed.%r%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, interruptable, main->context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify an empty string for the %[%r%r%] parameter to disable pid file creation for this program.%r", main->output.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, controller_long_pid_s, main->context.set.notable, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - //} - - controller_unlock_print_flush(main->output.to, 0); - - return F_none; - } -#endif // _di_controller_print_help_ - #ifndef _di_controller_main_ f_status_t controller_main(controller_main_t * const main, const f_console_arguments_t arguments) { @@ -120,7 +73,7 @@ extern "C" { if (main->parameters.array[controller_parameter_version_e].result == f_console_result_found_e) { controller_lock_print(main->output.to, 0); - fll_program_print_version(main->output.to, controller_program_version_s); + fll_program_print_version(main->message, controller_program_version_s); controller_unlock_print_flush(main->output.to, 0); diff --git a/level_3/controller/c/controller.h b/level_3/controller/c/controller.h index 3e3e032..d3ae9b5 100644 --- a/level_3/controller/c/controller.h +++ b/level_3/controller/c/controller.h @@ -82,21 +82,6 @@ extern "C" { #endif /** - * Print help. - * - * @param main - * The main program data. - * - * @return - * F_none on success. - * - * @see controller_main() - */ -#ifndef _di_controller_print_help_ - extern f_status_t controller_print_help(controller_main_t * const main); -#endif // _di_controller_print_help_ - -/** * Execute main program. * * Be sure to call controller_main_delete() after executing this. diff --git a/level_3/controller/c/controller/private-controller_print.c b/level_3/controller/c/controller/private-controller_print.c index 230c99e..863c3a3 100644 --- a/level_3/controller/c/controller/private-controller_print.c +++ b/level_3/controller/c/controller/private-controller_print.c @@ -45,24 +45,6 @@ extern "C" { } #endif // _di_controller_print_error_file_ -#ifndef _di_controller_print_signal_received_ - void controller_print_signal_received(controller_main_t * const main, const f_status_t signal) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_controller_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/controller/private-controller_print.h b/level_3/controller/c/controller/private-controller_print.h index 451ac21..ffce643 100644 --- a/level_3/controller/c/controller/private-controller_print.h +++ b/level_3/controller/c/controller/private-controller_print.h @@ -64,18 +64,6 @@ extern "C" { extern void controller_print_error_file(controller_thread_t * const thread, const fl_print_t print, const f_status_t status, const char *function, const bool fallback, const f_string_static_t name, const f_string_static_t operation, const uint8_t type) F_attribute_visibility_internal_d; #endif // _di_controller_print_error_file_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - * @param signal - * The signal received. - */ -#ifndef _di_controller_print_signal_received_ - extern void controller_print_signal_received(controller_main_t * const main, const f_status_t signal) F_attribute_visibility_internal_d; -#endif // _di_controller_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/lock/private-lock_print.c b/level_3/controller/c/lock/private-lock_print.c index 5613eec..0d53d9e 100644 --- a/level_3/controller/c/lock/private-lock_print.c +++ b/level_3/controller/c/lock/private-lock_print.c @@ -50,15 +50,15 @@ extern "C" { f_thread_mutex_lock(&thread->lock.print); } - flockfile(to.stream); + f_file_stream_lock(to); } #endif // _di_controller_lock_print_ #ifndef _di_controller_unlock_print_flush_ void controller_unlock_print_flush(const f_file_t to, controller_thread_t * const thread) { - f_file_stream_flush(to.stream); - funlockfile(to.stream); + f_file_stream_flush(to); + f_file_stream_unlock(to); if (thread) { f_thread_mutex_unlock(&thread->lock.print); diff --git a/level_3/controller/c/main.c b/level_3/controller/c/main.c index 39d9cda..9a81235 100644 --- a/level_3/controller/c/main.c +++ b/level_3/controller/c/main.c @@ -3,12 +3,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); - controller_main_t data = controller_main_t_initialize; + fll_program_data_t data = fll_program_data_t_initialize; + controller_setting_t setting = controller_setting_t_initialize; f_console_parameter_t parameters[] = controller_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = controller_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -41,7 +42,15 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { data.as_init = F_false; #endif // _controller_as_init_ - const f_status_t status = controller_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + controller_setting_load(arguments, &data, &setting); + } + + controller_main(&data, &setting); + + controller_setting_unload(&data, &setting); controller_main_delete(&data); @@ -52,7 +61,5 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { exit(data.child); } - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/controller/c/print.c b/level_3/controller/c/print.c new file mode 100644 index 0000000..4e41cd3 --- /dev/null +++ b/level_3/controller/c/print.c @@ -0,0 +1,84 @@ +#include "controller.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_controller_print_help_ + f_status_t controller_print_help(controller_setting_t * const setting, const fl_print_t print) { + + controller_lock_print(print.to, 0); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, *main->program_name_long, controller_program_version_s); + + fll_program_print_help_option_standard(print.to, context); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, controller_short_cgroup_s, controller_long_cgroup_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom control group file path, such as '" F_control_group_path_system_prefix_s F_control_group_path_system_default_s "'."); + fll_program_print_help_option(print, controller_short_daemon_s, controller_long_daemon_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run in daemon only mode (do not process the entry)."); + fll_program_print_help_option(print, controller_short_init_s, controller_long_init_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The program will run as an init replacement."); + fll_program_print_help_option(print, controller_short_interruptible_s, controller_long_interruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate that this program can be interrupted by a signal."); + fll_program_print_help_option(print, controller_short_pid_s, controller_long_pid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom pid file path, such as 'controller/run/default.pid'."); + fll_program_print_help_option(print, controller_short_settings_s, controller_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom settings path, such as 'controller/'."); + fll_program_print_help_option(print, controller_short_simulate_s, controller_long_simulate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Run as a simulation."); + fll_program_print_help_option(print, controller_short_socket_s, controller_long_socket_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom socket file path, such as 'controller/run/default.socket'."); + fll_program_print_help_option(print, controller_short_uninterruptible_s, controller_long_uninterruptible_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Designate that this program cannot be interrupted by a signal."); + fll_program_print_help_option(print, controller_short_validate_s, controller_long_validate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Validate the settings (entry and rules) without running (does not simulate)."); + + fll_program_print_help_usage(print, *main->program_name, controller_entry_s); + + fl_print_format("%r When both the %[%r%r%] parameter and the", print.to.stream, f_string_eol_s, print.set->notable, f_console_symbol_long_enable_s, controller_long_simulate_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter are specified, then additional information on each would be executed rule is printed but no simulation is performed.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, controller_long_validate_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + const f_string_static_t interruptable = main->as_init ? controller_long_uninterruptible_s : controller_long_interruptible_s; + + fl_print_format(" The default interrupt behavior is to operate as if the %[%r%r%] parameter is passed.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, interruptable, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify an empty string for the %[%r%r%] parameter to disable pid file creation for this program.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, controller_long_pid_s, print.set->notable, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + controller_unlock_print_flush(print.to, 0); + + return F_none; + } +#endif // _di_controller_print_help_ + +#ifndef _di_controller_print_line_first_ + void controller_print_line_first(controller_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_controller_print_line_first_ + +#ifndef _di_controller_print_line_last_ + void controller_print_line_last(controller_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & controller_main_flag_verify_e) return; + if ((setting->flag & controller_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_controller_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/controller/c/print.h b/level_3/controller/c/print.h new file mode 100644 index 0000000..c791d96 --- /dev/null +++ b/level_3/controller/c/print.h @@ -0,0 +1,70 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _controller_print_h +#define _controller_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param main + * The main program data. + * + * @return + * F_none on success. + * + * @see controller_main() + */ +#ifndef _di_controller_print_help_ + extern f_status_t controller_print_help(controller_main_t * const main); +#endif // _di_controller_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_controller_print_line_first_ + extern void controller_print_line_first(controller_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_controller_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_controller_print_line_last_ + extern void controller_print_line_last(controller_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_controller_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _controller_print_h diff --git a/level_3/controller/c/thread/private-thread.c b/level_3/controller/c/thread/private-thread.c index d5b401a..b448988 100644 --- a/level_3/controller/c/thread/private-thread.c +++ b/level_3/controller/c/thread/private-thread.c @@ -319,7 +319,7 @@ extern "C" { } if (F_status_set_fine(status) == F_interrupt) { - controller_print_signal_received(main, thread.signal); + fll_program_print_signal_received(main->warning, setting->line_first, thread.signal); if (main->output.verbosity != f_console_verbosity_quiet_e) { fll_print_dynamic_raw(f_string_eol_s, main->output.to.stream); diff --git a/level_3/controller/data/build/settings b/level_3/controller/data/build/settings index 299a0b2..4e0a994 100644 --- a/level_3/controller/data/build/settings +++ b/level_3/controller/data/build/settings @@ -24,7 +24,7 @@ build_libraries-individual -lf_account -lf_capability -lf_color -lf_console -lf_ build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library controller.c common.c +build_sources_library controller.c common.c print.c build_sources_library common/private-common.c common/private-cache.c common/private-control.c common/private-entry.c common/private-lock.c common/private-process.c common/private-rule.c common/private-setting.c common/private-thread.c build_sources_library control/private-control.c control/private-control_print.c build_sources_library controller/private-controller.c controller/private-controller_print.c @@ -36,7 +36,7 @@ build_sources_library thread/private-thread.c thread/private-thread_control.c th build_sources_program main.c main-common.c -build_sources_headers controller.h common.h +build_sources_headers controller.h common.h print.h build_sources_setting entries example rules diff --git a/level_3/fake/c/common.c b/level_3/fake/c/common.c index 7565db1..9f06812 100644 --- a/level_3/fake/c/common.c +++ b/level_3/fake/c/common.c @@ -115,6 +115,358 @@ extern "C" { const f_string_static_t fake_other_operation_skeleton_s = macro_f_string_static_t_initialize(FAKE_other_operation_skeleton_s, 0, FAKE_other_operation_skeleton_s_length); #endif // _di_fake_parameters_ +#ifndef _di_fake_setting_delete_ + f_status_t fake_setting_delete(fake_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fake_setting_delete_ + +#ifndef _di_fake_setting_load_ + void fake_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fake_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fake_parameter_no_color_e, fake_parameter_light_e, fake_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fake_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fake_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fake_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fake_parameter_verbosity_quiet_e, fake_parameter_verbosity_error_e, fake_parameter_verbosity_verbose_e, fake_parameter_verbosity_debug_e, fake_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fake_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fake_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fake_main_flag_help_e; + + return; + } + + if (main->parameters.array[fake_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fake_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fake_parameter_from_bytesequence_e, fake_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fake_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fake_parameter_from_bytesequence_e) { + if (setting->mode & fake_mode_from_codepoint_e) { + setting->mode -= fake_mode_from_codepoint_e; + } + + setting->mode |= fake_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fake_parameter_from_codepoint_e) { + if (setting->mode & fake_mode_from_bytesequence_e) { + setting->mode -= fake_mode_from_bytesequence_e; + } + + setting->mode |= fake_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fake_parameter_to_bytesequence_e, fake_parameter_to_codepoint_e, fake_parameter_to_combining_e, fake_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fake_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fake_parameter_to_bytesequence_e) { + if (setting->mode & fake_mode_to_codepoint_e) { + setting->mode -= fake_mode_to_codepoint_e; + } + + if (setting->mode & fake_mode_to_combining_e) { + setting->mode -= fake_mode_to_combining_e; + } + + if (setting->mode & fake_mode_to_width_e) { + setting->mode -= fake_mode_to_width_e; + } + + setting->mode |= fake_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fake_parameter_to_codepoint_e) { + if (setting->mode & fake_mode_to_bytesequence_e) { + setting->mode -= fake_mode_to_bytesequence_e; + } + + if (setting->mode & fake_mode_to_combining_e) { + setting->mode -= fake_mode_to_combining_e; + } + + if (setting->mode & fake_mode_to_width_e) { + setting->mode -= fake_mode_to_width_e; + } + + setting->mode |= fake_mode_to_codepoint_e; + } + else if (choices.array[choice] == fake_parameter_to_combining_e) { + if (setting->mode & fake_mode_to_bytesequence_e) { + setting->mode -= fake_mode_to_bytesequence_e; + } + + if (setting->mode & fake_mode_to_codepoint_e) { + setting->mode -= fake_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fake_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fake_mode_to_width_e; + } + + setting->mode |= fake_mode_to_combining_e; + } + else if (choices.array[choice] == fake_parameter_to_width_e) { + if (setting->mode & fake_mode_to_bytesequence_e) { + setting->mode -= fake_mode_to_bytesequence_e; + } + + if (setting->mode & fake_mode_to_codepoint_e) { + setting->mode -= fake_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fake_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fake_mode_to_combining_e; + } + + setting->mode |= fake_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fake_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fake_parameter_to_file_e].values.used > 1) { + fake_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fake_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fake_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fake_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fake_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fake_main_flag_file_to_e; + } + else { + fake_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fake_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fake_parameter_to_file_e].result == f_console_result_found_e) { + fake_print_error_no_value(main, setting, fake_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fake_main_flag_file_to_e) { + setting->flag -= fake_main_flag_file_to_e; + } + } + + if (main->parameters.array[fake_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fake_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fake_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fake_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fake_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fake_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fake_main_flag_file_from_e; + } + else if (main->parameters.array[fake_parameter_from_file_e].result == f_console_result_found_e) { + fake_print_error_no_value(main, setting, fake_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fake_main_flag_file_from_e) { + setting->flag -= fake_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fake_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fake_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fake_mode_to_bytesequence_e)) { + if (main->parameters.array[fake_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fake_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fake_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fake_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fake_main_flag_header_e; + } + + if (main->parameters.array[fake_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fake_main_flag_separate_e; + } + + if (main->parameters.array[fake_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fake_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fake_setting_load_ + +#ifndef _di_fake_setting_unload_ + f_status_t fake_setting_unload(fll_program_data_t * const main, fake_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fake_setting_delete(setting); + + return F_none; + } +#endif // _di_fake_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fake/c/common.h b/level_3/fake/c/common.h index 3dc0044..46ec2b0 100644 --- a/level_3/fake/c/common.h +++ b/level_3/fake/c/common.h @@ -457,6 +457,132 @@ extern "C" { #define fake_total_parameters_d 31 #endif // _di_fake_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fake_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fake_main_flag_e_ + enum { + fake_main_flag_none_e = 0x0, + fake_main_flag_file_from_e = 0x1, + fake_main_flag_file_to_e = 0x2, + fake_main_flag_header_e = 0x4, + fake_main_flag_help_e = 0x8, + fake_main_flag_separate_e = 0x10, + fake_main_flag_strip_invalid_e = 0x20, + fake_main_flag_verify_e = 0x40, + fake_main_flag_version_e = 0x80, + }; +#endif // _di_fake_main_flag_e_ + +/** + * The fake main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fake_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fake_setting_t; + + #define fake_setting_t_initialize \ + { \ + fake_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fake_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fake_setting_delete_ + extern f_status_t fake_setting_delete(fake_setting_t * const setting); +#endif // _di_fake_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fake_setting_load_ + extern void fake_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fake_setting_t * const setting); +#endif // _di_fake_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fake_setting_unload_ + extern f_status_t fake_setting_unload(fll_program_data_t * const main, fake_setting_t * const setting); +#endif // _di_fake_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fake/c/fake.c b/level_3/fake/c/fake.c index 273d146..002dcf6 100644 --- a/level_3/fake/c/fake.c +++ b/level_3/fake/c/fake.c @@ -13,83 +13,8 @@ extern "C" { #endif -#ifndef _di_fake_print_help_ - f_status_t fake_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fake_program_name_long_s, fake_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fake_short_define_s, fake_long_define_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Append an additional define after defines from settings file."); - fll_program_print_help_option(file, context, fake_short_fakefile_s, fake_long_fakefile_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Use this fakefile."); - fll_program_print_help_option(file, context, fake_short_mode_s, fake_long_mode_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use this mode when processing the build settings."); - fll_program_print_help_option(file, context, fake_short_process_s, fake_long_process_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Process name for storing build states."); - fll_program_print_help_option(file, context, fake_short_settings_s, fake_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Use this settings file."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fake_short_path_build_s, fake_long_path_build_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom build directory."); - fll_program_print_help_option(file, context, fake_short_path_data_s, fake_long_path_data_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom path to the data files."); - fll_program_print_help_option(file, context, fake_short_path_sources_s, fake_long_path_sources_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Specify a custom path to the source files."); - fll_program_print_help_option(file, context, fake_short_path_work_s, fake_long_path_work_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use includes/libraries/programs from this directory instead of system."); - - fl_print_format("%r%r %[Special Options:%] ", file.stream, f_string_eol_s, f_string_eol_s, context.set.important, context.set.important); - - fll_program_print_help_option_long(file, context, fake_long_documents_disabled_s, f_console_symbol_long_enable_s, " Forcibly do not build documents files."); - fll_program_print_help_option_long(file, context, fake_long_documents_enabled_s, f_console_symbol_long_enable_s, " Forcibly do build documents files."); - fll_program_print_help_option_long(file, context, fake_long_shared_disabled_s, f_console_symbol_long_enable_s, "Forcibly do not build shared files."); - fll_program_print_help_option_long(file, context, fake_long_shared_enabled_s, f_console_symbol_long_enable_s, " Forcibly do build shared files."); - fll_program_print_help_option_long(file, context, fake_long_static_disabled_s, f_console_symbol_long_enable_s, "Forcibly do not build static files."); - fll_program_print_help_option_long(file, context, fake_long_static_enabled_s, f_console_symbol_long_enable_s, " Forcibly do build static files."); - - fl_print_format("%r%r %[Operations:%] ", file.stream, f_string_eol_s, f_string_eol_s, context.set.important, context.set.important); - - fll_program_print_help_option_other(file, context, fake_other_operation_build_s, " Build or compile the code based on build settings file."); - fll_program_print_help_option_other(file, context, fake_other_operation_clean_s, " Delete all build files."); - fll_program_print_help_option_other(file, context, fake_other_operation_make_s, " Build or compile the code based on fakefile (default)."); - fll_program_print_help_option_other(file, context, fake_other_operation_skeleton_s, "Build a skeleton directory structure."); - - fll_program_print_help_usage(file, context, fake_program_name_s, fake_program_help_parameters_s); - - fl_print_format("%r When performing the %[%r%] operation, the", file.stream, f_string_eol_s, context.set.notable, fake_other_operation_build_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter specifies a name (limited to alpha-numeric, underscore, and dash) to be used in addition to the global.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fake_long_mode_s, context.set.notable, f_string_eol_s); - - fl_print_format(" For example, when a %[%r%]", file.stream, context.set.notable, fake_make_parameter_variable_mode_s, context.set.notable); - fl_print_format(" of 'fll_monolithic' is specified, build libraries from both 'build_libraries' and 'build_libraries-fll_monolithic' are used (but not 'build_libraries-fll_level').%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying the %[%r%] or the %[%r%]", file.stream, context.set.notable, fake_make_parameter_variable_fakefile_s, context.set.notable, context.set.notable, fake_make_parameter_variable_settings_s, context.set.notable); - fl_print_format(" parameters, the project root is seached first and then the build data director is searched when the given file does not contain a directory separator.%r", file.stream, f_string_eol_s); - - fl_print_format(" For example, with '%[%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%]' is used if found, but if it is not found then", file.stream, context.set.notable, context.set.notable); - fl_print_format(" '%[./%r%rmy_fakefile%]' is used if found.%r", file.stream, context.set.notable, fake_default_path_data_s, fake_default_path_build_s, context.set.notable, f_string_eol_s); - fl_print_format(" For example, with '%[%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%]' is used if found, but if it is not found then no other paths are attempted.%r%r", file.stream, context.set.notable, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When piping data to this program, the piped data is treated as if it were prepended to the %[%r%]", file.stream, context.set.notable, fake_make_parameter_variable_fakefile_s, context.set.notable); - fl_print_format("or the %[%r%], depending on the operation.%r", file.stream, context.set.notable, fake_make_parameter_variable_settings_s, context.set.notable, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fake_print_help_ - #ifndef _di_fake_main_ - f_status_t fake_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fake_main(fll_program_data_t * const main, fake_setting_t * const setting) { f_status_t status = F_none; @@ -137,13 +62,13 @@ 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_print_help(setting, main->message); 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); + fll_program_print_version(main->message, fake_program_version_s); return F_none; } @@ -405,7 +330,7 @@ extern "C" { if (F_status_set_fine(status) == F_interrupt || !(i % fake_signal_check_short_d)) { if (fll_program_standard_signal_received(main)) { - fake_print_signal_received(&data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fake/c/fake.h b/level_3/fake/c/fake.h index 7c7a326..972d326 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -97,21 +97,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fake_print_help_ - extern f_status_t fake_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fake_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -136,7 +121,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fake_main_ - extern f_status_t fake_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fake_main(fll_program_data_t * const main, fake_setting_t * const setting); #endif // _di_fake_main_ /** diff --git a/level_3/fake/c/main.c b/level_3/fake/c/main.c index 75db8a3..1a1da04 100644 --- a/level_3/fake/c/main.c +++ b/level_3/fake/c/main.c @@ -16,12 +16,13 @@ */ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fake_setting_t setting = fake_setting_t_initialize; f_console_parameter_t parameters[] = fake_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fake_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -31,7 +32,15 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { f_file_umask_get(&data.umask); - const f_status_t status = fake_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fake_setting_load(arguments, &data, &setting); + } + + fake_main(&data, &setting); + + fake_setting_unload(&data, &setting); fll_program_data_delete(&data); @@ -41,7 +50,5 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { exit(data.child); } - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fake/c/print.c b/level_3/fake/c/print.c new file mode 100644 index 0000000..ab66530 --- /dev/null +++ b/level_3/fake/c/print.c @@ -0,0 +1,112 @@ +#include "fake.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fake_print_help_ + f_status_t fake_print_help(fake_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fake_program_name_long_s, fake_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fake_short_define_s, fake_long_define_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Append an additional define after defines from settings file."); + fll_program_print_help_option(print, fake_short_fakefile_s, fake_long_fakefile_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Use this fakefile."); + fll_program_print_help_option(print, fake_short_mode_s, fake_long_mode_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use this mode when processing the build settings."); + fll_program_print_help_option(print, fake_short_process_s, fake_long_process_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Process name for storing build states."); + fll_program_print_help_option(print, fake_short_settings_s, fake_long_settings_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Use this settings file."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fake_short_path_build_s, fake_long_path_build_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom build directory."); + fll_program_print_help_option(print, fake_short_path_data_s, fake_long_path_data_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a custom path to the data files."); + fll_program_print_help_option(print, fake_short_path_sources_s, fake_long_path_sources_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Specify a custom path to the source files."); + fll_program_print_help_option(print, fake_short_path_work_s, fake_long_path_work_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use includes/libraries/programs from this directory instead of system."); + + fl_print_format("%r%r %[Special Options:%] ", print.to.stream, f_string_eol_s, f_string_eol_s, print.set->important, print.set->important); + + fll_program_print_help_option_long(print, fake_long_documents_disabled_s, f_console_symbol_long_enable_s, " Forcibly do not build documents files."); + fll_program_print_help_option_long(print, fake_long_documents_enabled_s, f_console_symbol_long_enable_s, " Forcibly do build documents files."); + fll_program_print_help_option_long(print, fake_long_shared_disabled_s, f_console_symbol_long_enable_s, "Forcibly do not build shared files."); + fll_program_print_help_option_long(print, fake_long_shared_enabled_s, f_console_symbol_long_enable_s, " Forcibly do build shared files."); + fll_program_print_help_option_long(print, fake_long_static_disabled_s, f_console_symbol_long_enable_s, "Forcibly do not build static files."); + fll_program_print_help_option_long(print, fake_long_static_enabled_s, f_console_symbol_long_enable_s, " Forcibly do build static files."); + + fl_print_format("%r%r %[Operations:%] ", print.to.stream, f_string_eol_s, f_string_eol_s, print.set->important, print.set->important); + + fll_program_print_help_option_other(print, fake_other_operation_build_s, " Build or compile the code based on build settings file."); + fll_program_print_help_option_other(print, fake_other_operation_clean_s, " Delete all build files."); + fll_program_print_help_option_other(print, fake_other_operation_make_s, " Build or compile the code based on fakefile (default)."); + fll_program_print_help_option_other(print, fake_other_operation_skeleton_s, "Build a skeleton directory structure."); + + fll_program_print_help_usage(print, fake_program_name_s, fake_program_help_parameters_s); + + fl_print_format("%r When performing the %[%r%] operation, the", print.to.stream, f_string_eol_s, print.set->notable, fake_other_operation_build_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter specifies a name (limited to alpha-numeric, underscore, and dash) to be used in addition to the global.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fake_long_mode_s, print.set->notable, f_string_eol_s); + + fl_print_format(" For example, when a %[%r%]", print.to.stream, print.set->notable, fake_make_parameter_variable_mode_s, print.set->notable); + fl_print_format(" of 'fll_monolithic' is specified, build libraries from both 'build_libraries' and 'build_libraries-fll_monolithic' are used (but not 'build_libraries-fll_level').%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying the %[%r%] or the %[%r%]", print.to.stream, print.set->notable, fake_make_parameter_variable_fakefile_s, print.set->notable, print.set->notable, fake_make_parameter_variable_settings_s, print.set->notable); + fl_print_format(" parameters, the project root is seached first and then the build data director is searched when the given file does not contain a directory separator.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For example, with '%[%r%r my_fakefile%]' the fakefile at", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fake_long_fakefile_s, print.set->notable); + fl_print_format(" '%[./my_fakefile%]' is used if found, but if it is not found then", print.to.stream, print.set->notable, print.set->notable); + fl_print_format(" '%[./%r%rmy_fakefile%]' is used if found.%r", print.to.stream, print.set->notable, fake_default_path_data_s, fake_default_path_build_s, print.set->notable, f_string_eol_s); + fl_print_format(" For example, with '%[%r%r ./my_fakefile%]' the fakefile at", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fake_long_fakefile_s, print.set->notable); + fl_print_format(" '%[./my_fakefile%]' is used if found, but if it is not found then no other paths are attempted.%r%r", print.to.stream, print.set->notable, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When piping data to this program, the piped data is treated as if it were prepended to the %[%r%]", print.to.stream, print.set->notable, fake_make_parameter_variable_fakefile_s, print.set->notable); + fl_print_format("or the %[%r%], depending on the operation.%r", print.to.stream, print.set->notable, fake_make_parameter_variable_settings_s, print.set->notable, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(output); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fake_print_help_ + +#ifndef _di_fake_print_line_first_ + void fake_print_line_first(fake_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fake_print_line_first_ + +#ifndef _di_fake_print_line_last_ + void fake_print_line_last(fake_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fake_main_flag_verify_e) return; + if ((setting->flag & fake_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fake_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fake/c/print.h b/level_3/fake/c/print.h new file mode 100644 index 0000000..4f10ebd --- /dev/null +++ b/level_3/fake/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fake_print_h +#define _fake_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fake_print_help_ + extern f_status_t fake_print_help(fake_setting_t * const setting, const fl_print_t print); +#endif // _di_fake_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fake_print_line_first_ + extern void fake_print_line_first(fake_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fake_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fake_print_line_last_ + extern void fake_print_line_last(fake_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fake_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fake_print_h diff --git a/level_3/fake/c/private-build-load.c b/level_3/fake/c/private-build-load.c index 51c0707..3faf748 100644 --- a/level_3/fake/c/private-build-load.c +++ b/level_3/fake/c/private-build-load.c @@ -75,7 +75,7 @@ extern "C" { if (F_status_is_error(*status)) return; if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); @@ -216,7 +216,7 @@ extern "C" { if (F_status_is_error(*status) && buffer.used) return; if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); @@ -1463,7 +1463,7 @@ extern "C" { if (F_status_is_error(*status)) return; if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); diff --git a/level_3/fake/c/private-build.c b/level_3/fake/c/private-build.c index df4bc55..99f1d16 100644 --- a/level_3/fake/c/private-build.c +++ b/level_3/fake/c/private-build.c @@ -348,7 +348,7 @@ extern "C" { if (F_status_is_error(*status) || f_file_exists(file_stage, F_true) == F_true || *status == F_child) return; if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); @@ -394,7 +394,7 @@ extern "C" { if (!(i % fake_signal_check_short_d)) { if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); @@ -714,7 +714,7 @@ extern "C" { f_string_dynamics_resize(0, &arguments); if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); } @@ -818,7 +818,7 @@ extern "C" { f_status_t fake_build_operate(fake_data_t * const data, const f_string_statics_t * const build_arguments, const bool process_pipe) { if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -1119,7 +1119,7 @@ extern "C" { if (F_status_is_error(*status)) return; if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); diff --git a/level_3/fake/c/private-fake.c b/level_3/fake/c/private-fake.c index a847f01..fd5bd8f 100644 --- a/level_3/fake/c/private-fake.c +++ b/level_3/fake/c/private-fake.c @@ -46,7 +46,7 @@ extern "C" { *status = fll_execute_program(program, arguments, ¶meter, 0, (void *) &return_code); if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); @@ -89,7 +89,7 @@ extern "C" { f_status_t fake_file_buffer(fake_data_t * const data, const f_string_static_t path_file, const bool required, f_string_dynamic_t * const buffer) { if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -173,7 +173,7 @@ extern "C" { do { if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -550,7 +550,7 @@ extern "C" { f_status_t fake_validate_parameter_paths(fake_data_t * const data) { if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fake/c/private-make-load_fakefile.c b/level_3/fake/c/private-make-load_fakefile.c index 26e3372..d63b29c 100644 --- a/level_3/fake/c/private-make-load_fakefile.c +++ b/level_3/fake/c/private-make-load_fakefile.c @@ -16,7 +16,7 @@ extern "C" { if (F_status_is_error(*status)) return; if (fll_program_standard_signal_received(data_make->main)) { - fake_print_signal_received(data_make->data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); @@ -120,7 +120,7 @@ extern "C" { if (!(i % fake_signal_check_short_d)) { if (fll_program_standard_signal_received(data_make->main)) { - fake_print_signal_received(data_make->data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); diff --git a/level_3/fake/c/private-make-operate.c b/level_3/fake/c/private-make-operate.c index d869d4d..501f3da 100644 --- a/level_3/fake/c/private-make-operate.c +++ b/level_3/fake/c/private-make-operate.c @@ -17,7 +17,7 @@ extern "C" { f_status_t fake_make_operate(fake_data_t * const data) { if (fll_program_standard_signal_received(data->main)) { - fake_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -1264,7 +1264,7 @@ extern "C" { if (!(i % fake_signal_check_short_d)) { if (fll_program_standard_signal_received(data_make->main)) { - fake_print_signal_received(data_make->data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); *status = F_status_set_error(F_interrupt); diff --git a/level_3/fake/c/private-make-operate_process.c b/level_3/fake/c/private-make-operate_process.c index 941910c..80f2714 100644 --- a/level_3/fake/c/private-make-operate_process.c +++ b/level_3/fake/c/private-make-operate_process.c @@ -287,7 +287,7 @@ extern "C" { if (!program.used && !arguments.used) return F_data_not; if (fll_program_standard_signal_received(data_make->main)) { - fake_print_signal_received(data_make->data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -363,7 +363,7 @@ extern "C" { status = fll_execute_program(program, arguments, ¶meter, 0, (void *) &return_code); if (fll_program_standard_signal_received(data_make->main)) { - fake_print_signal_received(data_make->data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fake/c/private-print.c b/level_3/fake/c/private-print.c index d2d06f3..6213226 100644 --- a/level_3/fake/c/private-print.c +++ b/level_3/fake/c/private-print.c @@ -537,24 +537,6 @@ extern "C" { } #endif // _di_fake_print_message_section_operation_unknown_ -#ifndef _di_fake_print_signal_received_ - void fake_print_signal_received(fake_data_t * const data) { - - if (data->main->warning.verbosity != f_console_verbosity_verbose_e && data->main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(data->main->warning.to.stream); - - flockfile(data->main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", data->main->warning.to.stream, data->main->context.set.reset, f_string_eol_s, f_string_eol_s, data->main->context.set.warning, data->main->context.set.warning); - fl_print_format("%[%i%]", data->main->warning.to.stream, data->main->context.set.notable, data->main->signal_received, data->main->context.set.notable); - fl_print_format("%[.%]%r", data->main->warning.to.stream, data->main->context.set.warning, data->main->context.set.warning, f_string_eol_s); - - funlockfile(data->main->warning.to.stream); - } -#endif // _di_fake_print_signal_received_ - #ifndef _di_fake_print_warning_settings_content_empty_ void fake_print_warning_settings_content_empty(fake_data_t * const data, const f_string_static_t path_file, const f_string_dynamic_t buffer, const f_string_range_t range_object, const f_string_static_t settings_name) { diff --git a/level_3/fake/c/private-print.h b/level_3/fake/c/private-print.h index 43381f7..02ba75e 100644 --- a/level_3/fake/c/private-print.h +++ b/level_3/fake/c/private-print.h @@ -352,21 +352,6 @@ extern "C" { #endif // _di_fake_print_message_section_operation_unknown_ /** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param data - * The program data. - * - * @see flockfile() - * @see funlockfile() - * - * @see fl_print_format() - */ -#ifndef _di_fake_print_signal_received_ - extern void fake_print_signal_received(fake_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_fake_print_signal_received_ - -/** * Print message when fake settings content is empty. * * @param data diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings index f776a89..9c80dfc 100644 --- a/level_3/fake/data/build/settings +++ b/level_3/fake/data/build/settings @@ -27,7 +27,7 @@ build_libraries-individual -lf_account -lf_capability -lf_color -lf_console -lf_ build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fake.c common.c +build_sources_library fake.c common.c print.c build_sources_library private-build.c private-build-library.c private-build-load.c private-build-object.c private-build-objects.c private-build-program.c private-build-skeleton.c build_sources_library private-clean.c private-common.c private-make.c private-print.c private-skeleton.c build_sources_library private-make-load_fakefile.c private-make-load_parameters.c @@ -36,7 +36,7 @@ build_sources_library private-fake.c private-fake-path_generate.c build_sources_program main.c -build_sources_headers fake.h common.h +build_sources_headers fake.h common.h print.h build_script yes build_shared yes diff --git a/level_3/firewall/c/common.c b/level_3/firewall/c/common.c index 2a64521..e921ce9 100644 --- a/level_3/firewall/c/common.c +++ b/level_3/firewall/c/common.c @@ -103,6 +103,358 @@ extern "C" { const f_string_static_t firewall_tool_ipset_s = macro_f_string_static_t_initialize(FIREWALL_tool_ipset_s, 0, FIREWALL_tool_ipset_s_length); #endif // _di_firewall_defines_ +#ifndef _di_firewall_setting_delete_ + f_status_t firewall_setting_delete(firewall_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_firewall_setting_delete_ + +#ifndef _di_firewall_setting_load_ + void firewall_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, firewall_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { firewall_parameter_no_color_e, firewall_parameter_light_e, firewall_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + firewall_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[firewall_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[firewall_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { firewall_parameter_verbosity_quiet_e, firewall_parameter_verbosity_error_e, firewall_parameter_verbosity_verbose_e, firewall_parameter_verbosity_debug_e, firewall_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + firewall_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[firewall_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= firewall_main_flag_help_e; + + return; + } + + if (main->parameters.array[firewall_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= firewall_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { firewall_parameter_from_bytesequence_e, firewall_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + firewall_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == firewall_parameter_from_bytesequence_e) { + if (setting->mode & firewall_mode_from_codepoint_e) { + setting->mode -= firewall_mode_from_codepoint_e; + } + + setting->mode |= firewall_mode_from_bytesequence_e; + } + else if (choices.array[choice] == firewall_parameter_from_codepoint_e) { + if (setting->mode & firewall_mode_from_bytesequence_e) { + setting->mode -= firewall_mode_from_bytesequence_e; + } + + setting->mode |= firewall_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { firewall_parameter_to_bytesequence_e, firewall_parameter_to_codepoint_e, firewall_parameter_to_combining_e, firewall_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + firewall_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == firewall_parameter_to_bytesequence_e) { + if (setting->mode & firewall_mode_to_codepoint_e) { + setting->mode -= firewall_mode_to_codepoint_e; + } + + if (setting->mode & firewall_mode_to_combining_e) { + setting->mode -= firewall_mode_to_combining_e; + } + + if (setting->mode & firewall_mode_to_width_e) { + setting->mode -= firewall_mode_to_width_e; + } + + setting->mode |= firewall_mode_to_bytesequence_e; + } + else if (choices.array[choice] == firewall_parameter_to_codepoint_e) { + if (setting->mode & firewall_mode_to_bytesequence_e) { + setting->mode -= firewall_mode_to_bytesequence_e; + } + + if (setting->mode & firewall_mode_to_combining_e) { + setting->mode -= firewall_mode_to_combining_e; + } + + if (setting->mode & firewall_mode_to_width_e) { + setting->mode -= firewall_mode_to_width_e; + } + + setting->mode |= firewall_mode_to_codepoint_e; + } + else if (choices.array[choice] == firewall_parameter_to_combining_e) { + if (setting->mode & firewall_mode_to_bytesequence_e) { + setting->mode -= firewall_mode_to_bytesequence_e; + } + + if (setting->mode & firewall_mode_to_codepoint_e) { + setting->mode -= firewall_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[firewall_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= firewall_mode_to_width_e; + } + + setting->mode |= firewall_mode_to_combining_e; + } + else if (choices.array[choice] == firewall_parameter_to_width_e) { + if (setting->mode & firewall_mode_to_bytesequence_e) { + setting->mode -= firewall_mode_to_bytesequence_e; + } + + if (setting->mode & firewall_mode_to_codepoint_e) { + setting->mode -= firewall_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[firewall_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= firewall_mode_to_combining_e; + } + + setting->mode |= firewall_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[firewall_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[firewall_parameter_to_file_e].values.used > 1) { + firewall_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[firewall_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[firewall_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[firewall_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[firewall_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= firewall_main_flag_file_to_e; + } + else { + firewall_print_error_parameter_file_name_empty(main, setting, main->parameters.array[firewall_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[firewall_parameter_to_file_e].result == f_console_result_found_e) { + firewall_print_error_no_value(main, setting, firewall_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & firewall_main_flag_file_to_e) { + setting->flag -= firewall_main_flag_file_to_e; + } + } + + if (main->parameters.array[firewall_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[firewall_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[firewall_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[firewall_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + firewall_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + firewall_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= firewall_main_flag_file_from_e; + } + else if (main->parameters.array[firewall_parameter_from_file_e].result == f_console_result_found_e) { + firewall_print_error_no_value(main, setting, firewall_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & firewall_main_flag_file_from_e) { + setting->flag -= firewall_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[firewall_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + firewall_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & firewall_mode_to_bytesequence_e)) { + if (main->parameters.array[firewall_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[firewall_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = firewall_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[firewall_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= firewall_main_flag_header_e; + } + + if (main->parameters.array[firewall_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= firewall_main_flag_separate_e; + } + + if (main->parameters.array[firewall_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= firewall_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_firewall_setting_load_ + +#ifndef _di_firewall_setting_unload_ + f_status_t firewall_setting_unload(fll_program_data_t * const main, firewall_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + firewall_setting_delete(setting); + + return F_none; + } +#endif // _di_firewall_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/firewall/c/common.h b/level_3/firewall/c/common.h index 410a4bc..b6893ed 100644 --- a/level_3/firewall/c/common.h +++ b/level_3/firewall/c/common.h @@ -409,6 +409,132 @@ extern "C" { #define firewall_total_parameters_d 17 #endif // _di_firewall_defines_ +/** + * Flags used to represent flags passed to the main function. + * + * firewall_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_firewall_main_flag_e_ + enum { + firewall_main_flag_none_e = 0x0, + firewall_main_flag_file_from_e = 0x1, + firewall_main_flag_file_to_e = 0x2, + firewall_main_flag_header_e = 0x4, + firewall_main_flag_help_e = 0x8, + firewall_main_flag_separate_e = 0x10, + firewall_main_flag_strip_invalid_e = 0x20, + firewall_main_flag_verify_e = 0x40, + firewall_main_flag_version_e = 0x80, + }; +#endif // _di_firewall_main_flag_e_ + +/** + * The firewall main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_firewall_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } firewall_setting_t; + + #define firewall_setting_t_initialize \ + { \ + firewall_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_firewall_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_firewall_setting_delete_ + extern f_status_t firewall_setting_delete(firewall_setting_t * const setting); +#endif // _di_firewall_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_firewall_setting_load_ + extern void firewall_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, firewall_setting_t * const setting); +#endif // _di_firewall_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_firewall_setting_unload_ + extern f_status_t firewall_setting_unload(fll_program_data_t * const main, firewall_setting_t * const setting); +#endif // _di_firewall_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/firewall/c/firewall.c b/level_3/firewall/c/firewall.c index 7bb364e..ca0f630 100644 --- a/level_3/firewall/c/firewall.c +++ b/level_3/firewall/c/firewall.c @@ -12,41 +12,8 @@ extern "C" { #endif -#ifndef _di_firewall_print_help_ - f_status_t firewall_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, firewall_program_name_long_s, firewall_program_version_s); - - fll_program_print_help_option_standard(file, context); - - fl_print_format("%r%r %[Commands:%] ", file.stream, f_string_eol_s, f_string_eol_s, context.set.important, context.set.important); - fl_print_format("%r %[%r%] Turn on the firewall.", file.stream, f_string_eol_s, context.set.standout, firewall_command_start_s, context.set.standout); - fl_print_format("%r %[%r%] Turn off the firewall.", file.stream, f_string_eol_s, context.set.standout, firewall_command_stop_s, context.set.standout); - fl_print_format("%r %[%r%] Turn off and then turn on the firewall.", file.stream, f_string_eol_s, context.set.standout, firewall_command_restart_s, context.set.standout); - fl_print_format("%r %[%r%] Prevent all communication.", file.stream, f_string_eol_s, context.set.standout, firewall_command_lock_s, context.set.standout); - fl_print_format("%r %[%r%] Show active firewall settings.", file.stream, f_string_eol_s, context.set.standout, firewall_command_show_s, context.set.standout); - - fll_program_print_help_usage(file, context, firewall_program_name_s, firewall_program_help_parameters_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_firewall_print_help_ - #ifndef _di_firewall_main_ - f_status_t firewall_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t firewall_main(fll_program_data_t * const main, firewall_setting_t * const setting) { f_status_t status = F_none; @@ -102,13 +69,13 @@ extern "C" { status = F_none; if (main->parameters.array[firewall_parameter_help_e].result == f_console_result_found_e) { - firewall_print_help(main->output.to, main->context); + firewall_print_help(setting, main->message); return F_none; } if (main->parameters.array[firewall_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, firewall_program_version_s); + fll_program_print_version(main->message, firewall_program_version_s); return F_none; } diff --git a/level_3/firewall/c/firewall.h b/level_3/firewall/c/firewall.h index 37032a5..b05ec3c 100644 --- a/level_3/firewall/c/firewall.h +++ b/level_3/firewall/c/firewall.h @@ -55,21 +55,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_firewall_print_help_ - extern f_status_t firewall_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_firewall_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -93,7 +78,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_firewall_main_ - extern f_status_t firewall_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t firewall_main(fll_program_data_t * const main, firewall_setting_t * const setting); #endif // _di_firewall_main_ #ifdef __cplusplus diff --git a/level_3/firewall/c/main.c b/level_3/firewall/c/main.c index 6a931ef..09a0c72 100644 --- a/level_3/firewall/c/main.c +++ b/level_3/firewall/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + firewall_setting_t setting = firewall_setting_t_initialize; f_console_parameter_t parameters[] = firewall_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = firewall_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,7 +16,15 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = firewall_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + firewall_setting_load(arguments, &data, &setting); + } + + firewall_main(&data, &setting); + + firewall_setting_unload(&data, &setting); fll_program_data_delete(&data); @@ -25,7 +34,5 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { exit(data.child); } - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/firewall/c/print.c b/level_3/firewall/c/print.c new file mode 100644 index 0000000..7c2eaea --- /dev/null +++ b/level_3/firewall/c/print.c @@ -0,0 +1,70 @@ +#include "firewall.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_firewall_print_help_ + f_status_t firewall_print_help(utf8_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, firewall_program_name_long_s, firewall_program_version_s); + + fll_program_print_help_option_standard(print); + + fl_print_format("%r%r %[Commands:%] ", print.to.stream, f_string_eol_s, f_string_eol_s, print.set->important, print.set->important); + fl_print_format("%r %[%r%] Turn on the firewall.", print.to.stream, f_string_eol_s, print.set->standout, firewall_command_start_s, print.set->standout); + fl_print_format("%r %[%r%] Turn off the firewall.", print.to.stream, f_string_eol_s, print.set->standout, firewall_command_stop_s, print.set->standout); + fl_print_format("%r %[%r%] Turn off and then turn on the firewall.", print.to.stream, f_string_eol_s, print.set->standout, firewall_command_restart_s, print.set->standout); + fl_print_format("%r %[%r%] Prevent all communication.", print.to.stream, f_string_eol_s, print.set->standout, firewall_command_lock_s, print.set->standout); + fl_print_format("%r %[%r%] Show active firewall settings.", print.to.stream, f_string_eol_s, print.set->standout, firewall_command_show_s, print.set->standout); + + fll_program_print_help_usage(print, firewall_program_name_s, firewall_program_help_parameters_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_firewall_print_help_ + +#ifndef _di_firewall_print_line_first_ + void firewall_print_line_first(firewall_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_firewall_print_line_first_ + +#ifndef _di_firewall_print_line_last_ + void firewall_print_line_last(firewall_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & firewall_main_flag_verify_e) return; + if ((setting->flag & firewall_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_firewall_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/firewall/c/print.h b/level_3/firewall/c/print.h new file mode 100644 index 0000000..f7ff2c4 --- /dev/null +++ b/level_3/firewall/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _firewall_print_h +#define _firewall_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_firewall_print_help_ + extern f_status_t firewall_print_help(firewall_setting_t * const setting, const fl_print_t print); +#endif // _di_firewall_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_firewall_print_line_first_ + extern void firewall_print_line_first(firewall_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_firewall_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_firewall_print_line_last_ + extern void firewall_print_line_last(firewall_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_firewall_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _firewall_print_h diff --git a/level_3/firewall/c/private-common.c b/level_3/firewall/c/private-common.c index dadb9e2..d20e756 100644 --- a/level_3/firewall/c/private-common.c +++ b/level_3/firewall/c/private-common.c @@ -85,24 +85,6 @@ void firewall_print_error_on_unhandled_for_file(const fl_print_t output, const c fll_print_format("%r%[%QAn unhandled error (%ui) has occurred while calling %s() for the file '%Q'.%]%r", output.to.stream, f_string_eol_s, output.context, output.prefix, status, function, filename, output.context, f_string_eol_s); } -#ifndef _di_firewall_print_signal_received_ - void firewall_print_signal_received(firewall_data_t * const data, const f_status_t signal) { - - if (data->main->warning.verbosity != f_console_verbosity_verbose_e && data->main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(data->main->warning.to.stream); - - flockfile(data->main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", data->main->warning.to.stream, data->main->context.set.reset, f_string_eol_s, f_string_eol_s, data->main->context.set.warning, data->main->context.set.warning); - fl_print_format("%[%i%]", data->main->warning.to.stream, data->main->context.set.notable, signal, data->main->context.set.notable); - fl_print_format("%[.%]%r", data->main->warning.to.stream, data->main->context.set.warning, data->main->context.set.warning, f_string_eol_s); - - funlockfile(data->main->warning.to.stream); - } -#endif // _di_firewall_print_signal_received_ - #ifndef _di_firewall_signal_received_ f_status_t firewall_signal_received(firewall_data_t * const data) { diff --git a/level_3/firewall/c/private-common.h b/level_3/firewall/c/private-common.h index 461cb90..b2c3b41 100644 --- a/level_3/firewall/c/private-common.h +++ b/level_3/firewall/c/private-common.h @@ -189,18 +189,6 @@ extern void firewall_print_error_on_unhandled(const fl_print_t output, const cha extern void firewall_print_error_on_unhandled_for_file(const fl_print_t output, const char *function, const f_status_t status, const f_string_static_t filename) F_attribute_visibility_internal_d; /** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param data - * The program data. - * @param signal - * The signal received. - */ -#ifndef _di_firewall_print_signal_received_ - extern void firewall_print_signal_received(firewall_data_t * const data, const f_status_t signal) F_attribute_visibility_internal_d; -#endif // _di_firewall_print_signal_received_ - -/** * Check to see if a process signal is received. * * Only signals that are blocked via main.signal will be received. diff --git a/level_3/firewall/data/build/settings b/level_3/firewall/data/build/settings index 223d867..4da5bf3 100644 --- a/level_3/firewall/data/build/settings +++ b/level_3/firewall/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_execute -lfll_fss -lfll_print -lfll build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library firewall.c common.c private-common.c private-firewall.c +build_sources_library firewall.c common.c print.c private-common.c private-firewall.c build_sources_program main.c -build_sources_headers firewall.h common.h +build_sources_headers firewall.h common.h print.h build_sources_setting default-blacklist default-whitelist example-device-firewall firewall-first firewall-last firewall-other diff --git a/level_3/fss_basic_list_read/c/common.c b/level_3/fss_basic_list_read/c/common.c index a31922b..63fb628 100644 --- a/level_3/fss_basic_list_read/c/common.c +++ b/level_3/fss_basic_list_read/c/common.c @@ -61,6 +61,358 @@ extern "C" { const f_string_static_t fss_basic_list_read_delimit_mode_name_lesser_s = macro_f_string_static_t_initialize(FSS_BASIC_LIST_READ_delimit_mode_name_lesser_s, 0, FSS_BASIC_LIST_READ_delimit_mode_name_lesser_s_length); #endif // _di_fss_basic_list_read_delimit_mode_ +#ifndef _di_fss_basic_list_read_setting_delete_ + f_status_t fss_basic_list_read_setting_delete(fss_basic_list_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_basic_list_read_setting_delete_ + +#ifndef _di_fss_basic_list_read_setting_load_ + void fss_basic_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_basic_list_read_parameter_no_color_e, fss_basic_list_read_parameter_light_e, fss_basic_list_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_list_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_basic_list_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_basic_list_read_parameter_verbosity_quiet_e, fss_basic_list_read_parameter_verbosity_error_e, fss_basic_list_read_parameter_verbosity_verbose_e, fss_basic_list_read_parameter_verbosity_debug_e, fss_basic_list_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_list_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_basic_list_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_basic_list_read_parameter_from_bytesequence_e, fss_basic_list_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_list_read_parameter_from_bytesequence_e) { + if (setting->mode & fss_basic_list_read_mode_from_codepoint_e) { + setting->mode -= fss_basic_list_read_mode_from_codepoint_e; + } + + setting->mode |= fss_basic_list_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_list_read_parameter_from_codepoint_e) { + if (setting->mode & fss_basic_list_read_mode_from_bytesequence_e) { + setting->mode -= fss_basic_list_read_mode_from_bytesequence_e; + } + + setting->mode |= fss_basic_list_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_basic_list_read_parameter_to_bytesequence_e, fss_basic_list_read_parameter_to_codepoint_e, fss_basic_list_read_parameter_to_combining_e, fss_basic_list_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_list_read_parameter_to_bytesequence_e) { + if (setting->mode & fss_basic_list_read_mode_to_codepoint_e) { + setting->mode -= fss_basic_list_read_mode_to_codepoint_e; + } + + if (setting->mode & fss_basic_list_read_mode_to_combining_e) { + setting->mode -= fss_basic_list_read_mode_to_combining_e; + } + + if (setting->mode & fss_basic_list_read_mode_to_width_e) { + setting->mode -= fss_basic_list_read_mode_to_width_e; + } + + setting->mode |= fss_basic_list_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_list_read_parameter_to_codepoint_e) { + if (setting->mode & fss_basic_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_basic_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_list_read_mode_to_combining_e) { + setting->mode -= fss_basic_list_read_mode_to_combining_e; + } + + if (setting->mode & fss_basic_list_read_mode_to_width_e) { + setting->mode -= fss_basic_list_read_mode_to_width_e; + } + + setting->mode |= fss_basic_list_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_basic_list_read_parameter_to_combining_e) { + if (setting->mode & fss_basic_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_basic_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_list_read_mode_to_codepoint_e) { + setting->mode -= fss_basic_list_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_list_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_list_read_mode_to_width_e; + } + + setting->mode |= fss_basic_list_read_mode_to_combining_e; + } + else if (choices.array[choice] == fss_basic_list_read_parameter_to_width_e) { + if (setting->mode & fss_basic_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_basic_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_list_read_mode_to_codepoint_e) { + setting->mode -= fss_basic_list_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_list_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_list_read_mode_to_combining_e; + } + + setting->mode |= fss_basic_list_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_basic_list_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_basic_list_read_parameter_to_file_e].values.used > 1) { + fss_basic_list_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_basic_list_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_basic_list_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_basic_list_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_basic_list_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_basic_list_read_main_flag_file_to_e; + } + else { + fss_basic_list_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_basic_list_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_basic_list_read_parameter_to_file_e].result == f_console_result_found_e) { + fss_basic_list_read_print_error_no_value(main, setting, fss_basic_list_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_basic_list_read_main_flag_file_to_e) { + setting->flag -= fss_basic_list_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_basic_list_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_basic_list_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_basic_list_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_basic_list_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_basic_list_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_basic_list_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_basic_list_read_main_flag_file_from_e; + } + else if (main->parameters.array[fss_basic_list_read_parameter_from_file_e].result == f_console_result_found_e) { + fss_basic_list_read_print_error_no_value(main, setting, fss_basic_list_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_basic_list_read_main_flag_file_from_e) { + setting->flag -= fss_basic_list_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_basic_list_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_basic_list_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_basic_list_read_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_basic_list_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_basic_list_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_basic_list_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_basic_list_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_read_main_flag_header_e; + } + + if (main->parameters.array[fss_basic_list_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_read_main_flag_separate_e; + } + + if (main->parameters.array[fss_basic_list_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_basic_list_read_setting_load_ + +#ifndef _di_fss_basic_list_read_setting_unload_ + f_status_t fss_basic_list_read_setting_unload(fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_basic_list_read_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_basic_list_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/common.h b/level_3/fss_basic_list_read/c/common.h index d5b5285..e2aca27 100644 --- a/level_3/fss_basic_list_read/c/common.h +++ b/level_3/fss_basic_list_read/c/common.h @@ -293,6 +293,132 @@ extern "C" { }; #endif // _di_fss_basic_list_read_delimit_modes_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_basic_list_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_basic_list_read_main_flag_e_ + enum { + fss_basic_list_read_main_flag_none_e = 0x0, + fss_basic_list_read_main_flag_file_from_e = 0x1, + fss_basic_list_read_main_flag_file_to_e = 0x2, + fss_basic_list_read_main_flag_header_e = 0x4, + fss_basic_list_read_main_flag_help_e = 0x8, + fss_basic_list_read_main_flag_separate_e = 0x10, + fss_basic_list_read_main_flag_strip_invalid_e = 0x20, + fss_basic_list_read_main_flag_verify_e = 0x40, + fss_basic_list_read_main_flag_version_e = 0x80, + }; +#endif // _di_fss_basic_list_read_main_flag_e_ + +/** + * The fss basic list read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_basic_list_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_basic_list_read_setting_t; + + #define fss_basic_list_read_setting_t_initialize \ + { \ + fss_basic_list_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_basic_list_read_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_basic_list_read_setting_delete_ + extern f_status_t fss_basic_list_read_setting_delete(fss_basic_list_read_setting_t * const setting); +#endif // _di_fss_basic_list_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_basic_list_read_setting_load_ + extern void fss_basic_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting); +#endif // _di_fss_basic_list_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_basic_list_read_setting_unload_ + extern f_status_t fss_basic_list_read_setting_unload(fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting); +#endif // _di_fss_basic_list_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.c b/level_3/fss_basic_list_read/c/fss_basic_list_read.c index 53f2c8e..1abbed3 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.c +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.c @@ -7,119 +7,8 @@ extern "C" { #endif -#ifndef _di_fss_basic_list_read_print_help_ - f_status_t fss_basic_list_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_basic_list_read_program_name_long_s, fss_basic_list_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_basic_list_read_short_at_s, fss_basic_list_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_content_s, fss_basic_list_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_columns_s, fss_basic_list_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_delimit_s, fss_basic_list_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_depth_s, fss_basic_list_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_empty_s, fss_basic_list_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_line_s, fss_basic_list_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_name_s, fss_basic_list_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_object_s, fss_basic_list_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_pipe_s, fss_basic_list_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_original_s, fss_basic_list_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_select_s, fss_basic_list_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_total_s, fss_basic_list_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(file, context, fss_basic_list_read_short_trim_s, fss_basic_list_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); - - fll_program_print_help_usage(file, context, fss_basic_list_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0002 Basic List standard.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", file.stream, f_string_eol_s); - fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, context.set.notable, f_string_eol_s); - - fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", file.stream, f_string_eol_s); - - fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_at_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", file.stream, f_string_eol_s); - fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_object_s, context.set.notable); - fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_total_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_at_s, context.set.notable); - fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_name_s, context.set.notable); - fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_at_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter value.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program may support parameters, such as %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, context.set.notable); - fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, context.set.notable, f_string_eol_s); - fl_print_format(" This is done to help ensure consistency for scripting.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, context.set.notable); - fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", file.stream, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, context.set.notable); - fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_trim_s, context.set.notable); - fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying both the %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_object_s, context.set.notable); - fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_content_s, context.set.notable, f_string_eol_s); - fl_print_format(" Both the Object and Content printed are already escaped.%r", file.stream, f_string_eol_s); - fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] accepts the following:%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Do not apply delimits.%r", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_none_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_all_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_object_s, context.set.notable, f_string_eol_s); - fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", file.stream, f_string_eol_s); - fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_greater_s, context.set.notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_lesser_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit_s, context.set.notable, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit_s, context.set.notable); - fl_print_format(" values %[%r%]", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_none_s, context.set.notable); - fl_print_format(" and %[%r%],", file.stream, context.set.notable, fss_basic_list_read_delimit_mode_name_all_s, context.set.notable); - fl_print_format(" overrule all other delimit values.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameters %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_columns_s, context.set.notable); - fl_print_format(" and %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, context.set.notable); - fl_print_format(" refer to a Content column.%r", file.stream, f_string_eol_s); - fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", file.stream, f_string_eol_s); - fl_print_format(" This is not to be confused with a depth.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_basic_list_read_print_help_ - #ifndef _di_fss_basic_list_read_main_ - f_status_t fss_basic_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_basic_list_read_main(fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting) { f_status_t status = F_none; @@ -169,13 +58,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_basic_list_read_parameter_help_e].result == f_console_result_found_e) { - fss_basic_list_read_print_help(main->output.to, main->context); + fss_basic_list_read_print_help(setting, main->message); return status; } if (main->parameters.array[fss_basic_list_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_basic_list_read_program_version_s); + fll_program_print_version(main->message, fss_basic_list_read_program_version_s); return status; } @@ -310,7 +199,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -507,7 +396,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -574,7 +463,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > fss_basic_list_read_block_max && fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_basic_list_read/c/fss_basic_list_read.h b/level_3/fss_basic_list_read/c/fss_basic_list_read.h index 857aca4..d6bc982 100644 --- a/level_3/fss_basic_list_read/c/fss_basic_list_read.h +++ b/level_3/fss_basic_list_read/c/fss_basic_list_read.h @@ -55,21 +55,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_basic_list_read_print_help_ - extern f_status_t fss_basic_list_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_basic_list_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -91,7 +76,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_basic_list_read_main_ - extern f_status_t fss_basic_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_basic_list_read_main(fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting); #endif // _di_fss_basic_list_read_main_ #ifdef __cplusplus diff --git a/level_3/fss_basic_list_read/c/main.c b/level_3/fss_basic_list_read/c/main.c index eac0224..f4f6dbc 100644 --- a/level_3/fss_basic_list_read/c/main.c +++ b/level_3/fss_basic_list_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_basic_list_read_setting_t setting = fss_basic_list_read_setting_t_initialize; f_console_parameter_t parameters[] = fss_basic_list_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_basic_list_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_basic_list_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_basic_list_read_setting_load(arguments, &data, &setting); + } + + fss_basic_list_read_main(&data, &setting); + + fss_basic_list_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_basic_list_read/c/print.c b/level_3/fss_basic_list_read/c/print.c new file mode 100644 index 0000000..c74adf8 --- /dev/null +++ b/level_3/fss_basic_list_read/c/print.c @@ -0,0 +1,148 @@ +#include "fss_basic_list_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_basic_list_read_print_help_ + f_status_t fss_basic_list_read_print_help(utf8_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_basic_list_read_program_name_long_s, fss_basic_list_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_basic_list_read_short_at_s, fss_basic_list_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(print, fss_basic_list_read_short_content_s, fss_basic_list_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); + fll_program_print_help_option(print, fss_basic_list_read_short_columns_s, fss_basic_list_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); + fll_program_print_help_option(print, fss_basic_list_read_short_delimit_s, fss_basic_list_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); + fll_program_print_help_option(print, fss_basic_list_read_short_depth_s, fss_basic_list_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(print, fss_basic_list_read_short_empty_s, fss_basic_list_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(print, fss_basic_list_read_short_line_s, fss_basic_list_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(print, fss_basic_list_read_short_name_s, fss_basic_list_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(print, fss_basic_list_read_short_object_s, fss_basic_list_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); + fll_program_print_help_option(print, fss_basic_list_read_short_pipe_s, fss_basic_list_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); + fll_program_print_help_option(print, fss_basic_list_read_short_original_s, fss_basic_list_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); + fll_program_print_help_option(print, fss_basic_list_read_short_select_s, fss_basic_list_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); + fll_program_print_help_option(print, fss_basic_list_read_short_total_s, fss_basic_list_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); + fll_program_print_help_option(print, fss_basic_list_read_short_trim_s, fss_basic_list_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); + + fll_program_print_help_usage(print, fss_basic_list_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0002 Basic List standard.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", print.to.stream, f_string_eol_s); + fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, print.set->notable, f_string_eol_s); + + fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", print.to.stream, f_string_eol_s); + + fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_at_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", print.to.stream, f_string_eol_s); + fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_object_s, print.set->notable); + fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_total_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_at_s, print.set->notable); + fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_name_s, print.set->notable); + fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_at_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter value.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program may support parameters, such as %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, print.set->notable); + fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, print.set->notable, f_string_eol_s); + fl_print_format(" This is done to help ensure consistency for scripting.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_depth_s, print.set->notable); + fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, print.set->notable); + fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_trim_s, print.set->notable); + fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying both the %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_object_s, print.set->notable); + fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_content_s, print.set->notable, f_string_eol_s); + fl_print_format(" Both the Object and Content printed are already escaped.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] accepts the following:%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Do not apply delimits.%r", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_none_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_all_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_object_s, print.set->notable, f_string_eol_s); + fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", print.to.stream, f_string_eol_s); + fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_greater_s, print.set->notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_lesser_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit_s, print.set->notable, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_delimit_s, print.set->notable); + fl_print_format(" values %[%r%]", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_none_s, print.set->notable); + fl_print_format(" and %[%r%],", print.to.stream, print.set->notable, fss_basic_list_read_delimit_mode_name_all_s, print.set->notable); + fl_print_format(" overrule all other delimit values.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameters %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_columns_s, print.set->notable); + fl_print_format(" and %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_read_long_select_s, print.set->notable); + fl_print_format(" refer to a Content column.%r", print.to.stream, f_string_eol_s); + fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This is not to be confused with a depth.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_basic_list_read_print_help_ + +#ifndef _di_fss_basic_list_read_print_line_first_ + void fss_basic_list_read_print_line_first(fss_basic_list_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_basic_list_read_print_line_first_ + +#ifndef _di_fss_basic_list_read_print_line_last_ + void fss_basic_list_read_print_line_last(fss_basic_list_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_basic_list_read_main_flag_verify_e) return; + if ((setting->flag & fss_basic_list_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_basic_list_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_basic_list_read/c/print.h b/level_3/fss_basic_list_read/c/print.h new file mode 100644 index 0000000..d75c2f3 --- /dev/null +++ b/level_3/fss_basic_list_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_basic_list_read_print_h +#define _fss_basic_list_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_list_read_print_help_ + extern f_status_t fss_basic_list_read_print_help(fss_basic_list_read_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_basic_list_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_list_read_print_line_first_ + extern void fss_basic_list_read_print_line_first(fss_basic_list_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_list_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_list_read_print_line_last_ + extern void fss_basic_list_read_print_line_last(fss_basic_list_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_list_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_basic_list_read_print_h diff --git a/level_3/fss_basic_list_read/c/private-common.c b/level_3/fss_basic_list_read/c/private-common.c index 7f1e7e8..a1861b3 100644 --- a/level_3/fss_basic_list_read/c/private-common.c +++ b/level_3/fss_basic_list_read/c/private-common.c @@ -56,24 +56,6 @@ extern "C" { } #endif // _di_fss_basic_list_read_depths_resize_ -#ifndef _di_fss_basic_list_read_print_signal_received_ - void fss_basic_list_read_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_basic_list_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/private-common.h b/level_3/fss_basic_list_read/c/private-common.h index 75cd604..7e94adb 100644 --- a/level_3/fss_basic_list_read/c/private-common.h +++ b/level_3/fss_basic_list_read/c/private-common.h @@ -261,16 +261,6 @@ extern "C" { extern f_status_t fss_basic_list_read_depths_resize(const f_array_length_t length, fss_basic_list_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_basic_list_read_depths_resize_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_basic_list_read_print_signal_received_ - extern void fss_basic_list_read_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_basic_list_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_read/c/private-read.c b/level_3/fss_basic_list_read/c/private-read.c index d327877..74c0333 100644 --- a/level_3/fss_basic_list_read/c/private-read.c +++ b/level_3/fss_basic_list_read/c/private-read.c @@ -88,7 +88,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -176,7 +176,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -357,7 +357,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -405,7 +405,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -508,7 +508,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -591,7 +591,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -631,7 +631,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -748,7 +748,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_basic_list_read/data/build/settings b/level_3/fss_basic_list_read/data/build/settings index 1bd1919..66d740e 100644 --- a/level_3/fss_basic_list_read/data/build/settings +++ b/level_3/fss_basic_list_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_basic_list_read.c common.c private-common.c private-print.c private-read.c +build_sources_library fss_basic_list_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers fss_basic_list_read.h common.h +build_sources_headers fss_basic_list_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_basic_list_write/c/common.c b/level_3/fss_basic_list_write/c/common.c index 87f363e..b3b1329 100644 --- a/level_3/fss_basic_list_write/c/common.c +++ b/level_3/fss_basic_list_write/c/common.c @@ -42,6 +42,358 @@ extern "C" { const f_string_static_t fss_basic_list_write_long_trim_s = macro_f_string_static_t_initialize(FSS_BASIC_LIST_WRITE_long_trim_s, 0, FSS_BASIC_LIST_WRITE_long_trim_s_length); #endif // _di_fss_basic_list_write_parameters_ +#ifndef _di_fss_basic_list_write_setting_delete_ + f_status_t fss_basic_list_write_setting_delete(fss_basic_list_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_basic_list_write_setting_delete_ + +#ifndef _di_fss_basic_list_write_setting_load_ + void fss_basic_list_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_basic_list_write_parameter_no_color_e, fss_basic_list_write_parameter_light_e, fss_basic_list_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_list_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_basic_list_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_basic_list_write_parameter_verbosity_quiet_e, fss_basic_list_write_parameter_verbosity_error_e, fss_basic_list_write_parameter_verbosity_verbose_e, fss_basic_list_write_parameter_verbosity_debug_e, fss_basic_list_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_list_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_basic_list_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_basic_list_write_parameter_from_bytesequence_e, fss_basic_list_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_list_write_parameter_from_bytesequence_e) { + if (setting->mode & fss_basic_list_write_mode_from_codepoint_e) { + setting->mode -= fss_basic_list_write_mode_from_codepoint_e; + } + + setting->mode |= fss_basic_list_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_list_write_parameter_from_codepoint_e) { + if (setting->mode & fss_basic_list_write_mode_from_bytesequence_e) { + setting->mode -= fss_basic_list_write_mode_from_bytesequence_e; + } + + setting->mode |= fss_basic_list_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_basic_list_write_parameter_to_bytesequence_e, fss_basic_list_write_parameter_to_codepoint_e, fss_basic_list_write_parameter_to_combining_e, fss_basic_list_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_list_write_parameter_to_bytesequence_e) { + if (setting->mode & fss_basic_list_write_mode_to_codepoint_e) { + setting->mode -= fss_basic_list_write_mode_to_codepoint_e; + } + + if (setting->mode & fss_basic_list_write_mode_to_combining_e) { + setting->mode -= fss_basic_list_write_mode_to_combining_e; + } + + if (setting->mode & fss_basic_list_write_mode_to_width_e) { + setting->mode -= fss_basic_list_write_mode_to_width_e; + } + + setting->mode |= fss_basic_list_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_list_write_parameter_to_codepoint_e) { + if (setting->mode & fss_basic_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_basic_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_list_write_mode_to_combining_e) { + setting->mode -= fss_basic_list_write_mode_to_combining_e; + } + + if (setting->mode & fss_basic_list_write_mode_to_width_e) { + setting->mode -= fss_basic_list_write_mode_to_width_e; + } + + setting->mode |= fss_basic_list_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_basic_list_write_parameter_to_combining_e) { + if (setting->mode & fss_basic_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_basic_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_list_write_mode_to_codepoint_e) { + setting->mode -= fss_basic_list_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_list_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_list_write_mode_to_width_e; + } + + setting->mode |= fss_basic_list_write_mode_to_combining_e; + } + else if (choices.array[choice] == fss_basic_list_write_parameter_to_width_e) { + if (setting->mode & fss_basic_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_basic_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_list_write_mode_to_codepoint_e) { + setting->mode -= fss_basic_list_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_list_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_list_write_mode_to_combining_e; + } + + setting->mode |= fss_basic_list_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_basic_list_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_basic_list_write_parameter_to_file_e].values.used > 1) { + fss_basic_list_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_basic_list_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_basic_list_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_basic_list_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_basic_list_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_basic_list_write_main_flag_file_to_e; + } + else { + fss_basic_list_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_basic_list_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_basic_list_write_parameter_to_file_e].result == f_console_result_found_e) { + fss_basic_list_write_print_error_no_value(main, setting, fss_basic_list_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_basic_list_write_main_flag_file_to_e) { + setting->flag -= fss_basic_list_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_basic_list_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_basic_list_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_basic_list_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_basic_list_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_basic_list_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_basic_list_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_basic_list_write_main_flag_file_from_e; + } + else if (main->parameters.array[fss_basic_list_write_parameter_from_file_e].result == f_console_result_found_e) { + fss_basic_list_write_print_error_no_value(main, setting, fss_basic_list_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_basic_list_write_main_flag_file_from_e) { + setting->flag -= fss_basic_list_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_basic_list_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_basic_list_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_basic_list_write_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_basic_list_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_basic_list_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_basic_list_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_basic_list_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_write_main_flag_header_e; + } + + if (main->parameters.array[fss_basic_list_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_write_main_flag_separate_e; + } + + if (main->parameters.array[fss_basic_list_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_list_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_basic_list_write_setting_load_ + +#ifndef _di_fss_basic_list_write_setting_unload_ + f_status_t fss_basic_list_write_setting_unload(fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_basic_list_write_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_basic_list_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_write/c/common.h b/level_3/fss_basic_list_write/c/common.h index 3a7985b..6712563 100644 --- a/level_3/fss_basic_list_write/c/common.h +++ b/level_3/fss_basic_list_write/c/common.h @@ -208,6 +208,132 @@ extern "C" { #define fss_basic_list_write_total_parameters_d 21 #endif // _di_fss_basic_list_write_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_basic_list_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_basic_list_write_main_flag_e_ + enum { + fss_basic_list_write_main_flag_none_e = 0x0, + fss_basic_list_write_main_flag_file_from_e = 0x1, + fss_basic_list_write_main_flag_file_to_e = 0x2, + fss_basic_list_write_main_flag_header_e = 0x4, + fss_basic_list_write_main_flag_help_e = 0x8, + fss_basic_list_write_main_flag_separate_e = 0x10, + fss_basic_list_write_main_flag_strip_invalid_e = 0x20, + fss_basic_list_write_main_flag_verify_e = 0x40, + fss_basic_list_write_main_flag_version_e = 0x80, + }; +#endif // _di_fss_basic_list_write_main_flag_e_ + +/** + * The fss basic list write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_basic_list_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_basic_list_write_setting_t; + + #define fss_basic_list_write_setting_t_initialize \ + { \ + fss_basic_list_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_basic_list_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_basic_list_write_setting_delete_ + extern f_status_t fss_basic_list_write_setting_delete(fss_basic_list_write_setting_t * const setting); +#endif // _di_fss_basic_list_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_basic_list_write_setting_load_ + extern void fss_basic_list_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting); +#endif // _di_fss_basic_list_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_basic_list_write_setting_unload_ + extern f_status_t fss_basic_list_write_setting_unload(fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting); +#endif // _di_fss_basic_list_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.c b/level_3/fss_basic_list_write/c/fss_basic_list_write.c index 3c233d0..311fb52 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.c +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.c @@ -6,59 +6,8 @@ extern "C" { #endif -#ifndef _di_fss_basic_list_write_print_help_ - f_status_t fss_basic_list_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_basic_list_write_program_name_long_s, fss_basic_list_write_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_basic_list_write_short_file_s, fss_basic_list_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_content_s, fss_basic_list_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_double_s, fss_basic_list_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_ignore_s, fss_basic_list_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_object_s, fss_basic_list_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_partial_s, fss_basic_list_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_prepend_s, fss_basic_list_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_single_s, fss_basic_list_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - fll_program_print_help_option(file, context, fss_basic_list_write_short_trim_s, fss_basic_list_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); - - fll_program_print_help_usage(file, context, fss_basic_list_write_program_name_s, f_string_empty_s); - - fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", file.stream, f_string_eol_s, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The FSS-0002 (Basic List) specification does not support quoted names, therefore the parameters '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_single_s, context.set.notable); - fl_print_format(" and '%[%r%r%]' do nothing.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_double_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_ignore_s, context.set.notable, f_string_eol_s); - fl_print_format(" This parameter requires two values.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_basic_list_write_print_help_ - #ifndef _di_fss_basic_list_write_main_ - f_status_t fss_basic_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_basic_list_write_main(fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting) { f_status_t status = F_none; @@ -110,13 +59,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_basic_list_write_parameter_help_e].result == f_console_result_found_e) { - fss_basic_list_write_print_help(main->output.to, main->context); + fss_basic_list_write_print_help(setting, main->message); return status; } if (main->parameters.array[fss_basic_list_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_basic_list_write_program_version_s); + fll_program_print_version(main->message, fss_basic_list_write_program_version_s); return status; } @@ -408,7 +357,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -429,7 +378,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -451,7 +400,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_basic_list_write/c/fss_basic_list_write.h b/level_3/fss_basic_list_write/c/fss_basic_list_write.h index 7e896fc..251c719 100644 --- a/level_3/fss_basic_list_write/c/fss_basic_list_write.h +++ b/level_3/fss_basic_list_write/c/fss_basic_list_write.h @@ -47,21 +47,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_basic_list_write_print_help_ - extern f_status_t fss_basic_list_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_basic_list_write_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -74,16 +59,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_basic_list_write_main_ - extern f_status_t fss_basic_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_basic_list_write_main(fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting); #endif // _di_fss_basic_list_write_main_ #ifdef __cplusplus diff --git a/level_3/fss_basic_list_write/c/main.c b/level_3/fss_basic_list_write/c/main.c index 1809514..fd6a53b 100644 --- a/level_3/fss_basic_list_write/c/main.c +++ b/level_3/fss_basic_list_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_basic_list_write_setting_t setting = fss_basic_list_write_setting_t_initialize; f_console_parameter_t parameters[] = fss_basic_list_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_basic_list_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,21 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_basic_list_write_setting_load(arguments, &data, &setting); + } + const f_status_t status = fss_basic_list_write_main(&data, arguments); + fss_basic_list_write_main(&data, &setting); + + fss_basic_list_write_setting_unload(&data, &setting); + fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_basic_list_write/c/print.c b/level_3/fss_basic_list_write/c/print.c new file mode 100644 index 0000000..10b3659 --- /dev/null +++ b/level_3/fss_basic_list_write/c/print.c @@ -0,0 +1,88 @@ +#include "fss_basic_list_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_basic_list_write_print_help_ + f_status_t fss_basic_list_write_print_help(utf8_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_basic_list_write_program_name_long_s, fss_basic_list_write_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_basic_list_write_short_file_s, fss_basic_list_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, fss_basic_list_write_short_content_s, fss_basic_list_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, fss_basic_list_write_short_double_s, fss_basic_list_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, fss_basic_list_write_short_ignore_s, fss_basic_list_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); + fll_program_print_help_option(print, fss_basic_list_write_short_object_s, fss_basic_list_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, fss_basic_list_write_short_partial_s, fss_basic_list_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); + fll_program_print_help_option(print, fss_basic_list_write_short_prepend_s, fss_basic_list_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); + fll_program_print_help_option(print, fss_basic_list_write_short_single_s, fss_basic_list_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + fll_program_print_help_option(print, fss_basic_list_write_short_trim_s, fss_basic_list_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); + + fll_program_print_help_usage(print, fss_basic_list_write_program_name_s, f_string_empty_s); + + fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", print.to.stream, f_string_eol_s, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The FSS-0002 (Basic List) specification does not support quoted names, therefore the parameters '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_single_s, print.set->notable); + fl_print_format(" and '%[%r%r%]' do nothing.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_double_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_list_write_long_ignore_s, print.set->notable, f_string_eol_s); + fl_print_format(" This parameter requires two values.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_basic_list_write_print_help_ + +#ifndef _di_fss_basic_list_write_print_line_first_ + void fss_basic_list_write_print_line_first(fss_basic_list_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_basic_list_write_print_line_first_ + +#ifndef _di_fss_basic_list_write_print_line_last_ + void fss_basic_list_write_print_line_last(fss_basic_list_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_basic_list_write_main_flag_verify_e) return; + if ((setting->flag & fss_basic_list_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_basic_list_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_basic_list_write/c/print.h b/level_3/fss_basic_list_write/c/print.h new file mode 100644 index 0000000..12ddbc0 --- /dev/null +++ b/level_3/fss_basic_list_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_basic_list_write_print_h +#define _fss_basic_list_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_list_write_print_help_ + extern f_status_t fss_basic_list_write_print_help(fss_basic_list_write_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_basic_list_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_list_write_print_line_first_ + extern void fss_basic_list_write_print_line_first(fss_basic_list_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_list_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_list_write_print_line_last_ + extern void fss_basic_list_write_print_line_last(fss_basic_list_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_list_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_basic_list_write_print_h diff --git a/level_3/fss_basic_list_write/c/private-common.c b/level_3/fss_basic_list_write/c/private-common.c index d62960d..1975491 100644 --- a/level_3/fss_basic_list_write/c/private-common.c +++ b/level_3/fss_basic_list_write/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_basic_list_write_print_signal_received_ - void fss_basic_list_write_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_basic_list_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_write/c/private-common.h b/level_3/fss_basic_list_write/c/private-common.h index b4be76a..13524a4 100644 --- a/level_3/fss_basic_list_write/c/private-common.h +++ b/level_3/fss_basic_list_write/c/private-common.h @@ -24,16 +24,6 @@ extern "C" { #define fss_basic_list_write_common_allocation_small_d 128 #endif // _di_fss_basic_list_write_common_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_basic_list_write_print_signal_received_ - extern void fss_basic_list_write_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_basic_list_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_list_write/c/private-write.c b/level_3/fss_basic_list_write/c/private-write.c index 62ee9dd..4d3d125 100644 --- a/level_3/fss_basic_list_write/c/private-write.c +++ b/level_3/fss_basic_list_write/c/private-write.c @@ -164,7 +164,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_basic_list_write/data/build/settings b/level_3/fss_basic_list_write/data/build/settings index 2168e14..f92a448 100644 --- a/level_3/fss_basic_list_write/data/build/settings +++ b/level_3/fss_basic_list_write/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_basic_list_write.c common.c private-common.c private-write.c +build_sources_library fss_basic_list_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers fss_basic_list_write.h common.h +build_sources_headers fss_basic_list_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_basic_read/c/common.c b/level_3/fss_basic_read/c/common.c index b9c097a..923d37c 100644 --- a/level_3/fss_basic_read/c/common.c +++ b/level_3/fss_basic_read/c/common.c @@ -60,6 +60,358 @@ extern "C" { const f_string_static_t fss_basic_read_delimit_mode_name_lesser_s = macro_f_string_static_t_initialize(FSS_BASIC_READ_delimit_mode_name_lesser_s, 0, FSS_BASIC_READ_delimit_mode_name_lesser_s_length); #endif // _di_fss_basic_read_delimit_mode_ +#ifndef _di_fss_basic_read_setting_delete_ + f_status_t fss_basic_read_setting_delete(fss_basic_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_basic_read_setting_delete_ + +#ifndef _di_fss_basic_read_setting_load_ + void fss_basic_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_basic_read_parameter_no_color_e, fss_basic_read_parameter_light_e, fss_basic_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_basic_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_basic_read_parameter_verbosity_quiet_e, fss_basic_read_parameter_verbosity_error_e, fss_basic_read_parameter_verbosity_verbose_e, fss_basic_read_parameter_verbosity_debug_e, fss_basic_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_basic_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_basic_read_parameter_from_bytesequence_e, fss_basic_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_read_parameter_from_bytesequence_e) { + if (setting->mode & fss_basic_read_mode_from_codepoint_e) { + setting->mode -= fss_basic_read_mode_from_codepoint_e; + } + + setting->mode |= fss_basic_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_read_parameter_from_codepoint_e) { + if (setting->mode & fss_basic_read_mode_from_bytesequence_e) { + setting->mode -= fss_basic_read_mode_from_bytesequence_e; + } + + setting->mode |= fss_basic_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_basic_read_parameter_to_bytesequence_e, fss_basic_read_parameter_to_codepoint_e, fss_basic_read_parameter_to_combining_e, fss_basic_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_read_parameter_to_bytesequence_e) { + if (setting->mode & fss_basic_read_mode_to_codepoint_e) { + setting->mode -= fss_basic_read_mode_to_codepoint_e; + } + + if (setting->mode & fss_basic_read_mode_to_combining_e) { + setting->mode -= fss_basic_read_mode_to_combining_e; + } + + if (setting->mode & fss_basic_read_mode_to_width_e) { + setting->mode -= fss_basic_read_mode_to_width_e; + } + + setting->mode |= fss_basic_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_read_parameter_to_codepoint_e) { + if (setting->mode & fss_basic_read_mode_to_bytesequence_e) { + setting->mode -= fss_basic_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_read_mode_to_combining_e) { + setting->mode -= fss_basic_read_mode_to_combining_e; + } + + if (setting->mode & fss_basic_read_mode_to_width_e) { + setting->mode -= fss_basic_read_mode_to_width_e; + } + + setting->mode |= fss_basic_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_basic_read_parameter_to_combining_e) { + if (setting->mode & fss_basic_read_mode_to_bytesequence_e) { + setting->mode -= fss_basic_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_read_mode_to_codepoint_e) { + setting->mode -= fss_basic_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_read_mode_to_width_e; + } + + setting->mode |= fss_basic_read_mode_to_combining_e; + } + else if (choices.array[choice] == fss_basic_read_parameter_to_width_e) { + if (setting->mode & fss_basic_read_mode_to_bytesequence_e) { + setting->mode -= fss_basic_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_read_mode_to_codepoint_e) { + setting->mode -= fss_basic_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_read_mode_to_combining_e; + } + + setting->mode |= fss_basic_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_basic_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_basic_read_parameter_to_file_e].values.used > 1) { + fss_basic_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_basic_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_basic_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_basic_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_basic_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_basic_read_main_flag_file_to_e; + } + else { + fss_basic_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_basic_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_basic_read_parameter_to_file_e].result == f_console_result_found_e) { + fss_basic_read_print_error_no_value(main, setting, fss_basic_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_basic_read_main_flag_file_to_e) { + setting->flag -= fss_basic_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_basic_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_basic_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_basic_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_basic_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_basic_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_basic_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_basic_read_main_flag_file_from_e; + } + else if (main->parameters.array[fss_basic_read_parameter_from_file_e].result == f_console_result_found_e) { + fss_basic_read_print_error_no_value(main, setting, fss_basic_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_basic_read_main_flag_file_from_e) { + setting->flag -= fss_basic_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_basic_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_basic_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_basic_read_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_basic_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_basic_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_basic_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_basic_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_read_main_flag_header_e; + } + + if (main->parameters.array[fss_basic_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_read_main_flag_separate_e; + } + + if (main->parameters.array[fss_basic_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_basic_read_setting_load_ + +#ifndef _di_fss_basic_read_setting_unload_ + f_status_t fss_basic_read_setting_unload(fll_program_data_t * const main, fss_basic_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_basic_read_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_basic_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_read/c/common.h b/level_3/fss_basic_read/c/common.h index 33b2f01..d02c6fd 100644 --- a/level_3/fss_basic_read/c/common.h +++ b/level_3/fss_basic_read/c/common.h @@ -293,6 +293,132 @@ extern "C" { }; #endif // _di_fss_basic_read_delimit_modes_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_basic_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_basic_read_main_flag_e_ + enum { + fss_basic_read_main_flag_none_e = 0x0, + fss_basic_read_main_flag_file_from_e = 0x1, + fss_basic_read_main_flag_file_to_e = 0x2, + fss_basic_read_main_flag_header_e = 0x4, + fss_basic_read_main_flag_help_e = 0x8, + fss_basic_read_main_flag_separate_e = 0x10, + fss_basic_read_main_flag_strip_invalid_e = 0x20, + fss_basic_read_main_flag_verify_e = 0x40, + fss_basic_read_main_flag_version_e = 0x80, + }; +#endif // _di_fss_basic_read_main_flag_e_ + +/** + * The fss basic read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_basic_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_basic_read_setting_t; + + #define fss_basic_read_setting_t_initialize \ + { \ + fss_basic_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_basic_read_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_basic_read_setting_delete_ + extern f_status_t fss_basic_read_setting_delete(fss_basic_read_setting_t * const setting); +#endif // _di_fss_basic_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_basic_read_setting_load_ + extern void fss_basic_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_read_setting_t * const setting); +#endif // _di_fss_basic_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_basic_read_setting_unload_ + extern f_status_t fss_basic_read_setting_unload(fll_program_data_t * const main, fss_basic_read_setting_t * const setting); +#endif // _di_fss_basic_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_read/c/fss_basic_read.c b/level_3/fss_basic_read/c/fss_basic_read.c index 71a178b..5aee79c 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.c +++ b/level_3/fss_basic_read/c/fss_basic_read.c @@ -7,119 +7,8 @@ extern "C" { #endif -#ifndef _di_fss_basic_read_print_help_ - f_status_t fss_basic_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_basic_read_program_name_long_s, fss_basic_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_basic_read_short_at_s, fss_basic_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); - fll_program_print_help_option(file, context, fss_basic_read_short_content_s, fss_basic_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); - fll_program_print_help_option(file, context, fss_basic_read_short_columns_s, fss_basic_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); - fll_program_print_help_option(file, context, fss_basic_read_short_delimit_s, fss_basic_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(file, context, fss_basic_read_short_depth_s, fss_basic_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); - fll_program_print_help_option(file, context, fss_basic_read_short_empty_s, fss_basic_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); - fll_program_print_help_option(file, context, fss_basic_read_short_line_s, fss_basic_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); - fll_program_print_help_option(file, context, fss_basic_read_short_name_s, fss_basic_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); - fll_program_print_help_option(file, context, fss_basic_read_short_object_s, fss_basic_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); - fll_program_print_help_option(file, context, fss_basic_read_short_pipe_s, fss_basic_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(file, context, fss_basic_read_short_original_s, fss_basic_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); - fll_program_print_help_option(file, context, fss_basic_read_short_select_s, fss_basic_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); - fll_program_print_help_option(file, context, fss_basic_read_short_total_s, fss_basic_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(file, context, fss_basic_read_short_trim_s, fss_basic_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); - - fll_program_print_help_usage(file, context, fss_basic_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0000 Basic standard.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", file.stream, f_string_eol_s); - fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, context.set.notable, f_string_eol_s); - - fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", file.stream, f_string_eol_s); - - fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_at_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", file.stream, f_string_eol_s); - fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_object_s, context.set.notable); - fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_total_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_at_s, context.set.notable); - fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_name_s, context.set.notable); - fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_at_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter value.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program may support parameters, such as %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, context.set.notable); - fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, context.set.notable, f_string_eol_s); - fl_print_format(" This is done to help ensure consistency for scripting.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, context.set.notable); - fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", file.stream, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, context.set.notable); - fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_trim_s, context.set.notable); - fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying both the %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_object_s, context.set.notable); - fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_content_s, context.set.notable, f_string_eol_s); - fl_print_format(" Both the Object and Content printed are already escaped.%r", file.stream, f_string_eol_s); - fl_print_format(" Both the Object and Content are separated by a space.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] accepts the following:%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_delimit_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Do not apply delimits.%r", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_none_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_all_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_object_s, context.set.notable, f_string_eol_s); - fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", file.stream, f_string_eol_s); - fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_greater_s, context.set.notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_lesser_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_delimit_s, context.set.notable, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_delimit_s, context.set.notable); - fl_print_format(" values %[%r%]", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_none_s, context.set.notable); - fl_print_format(" and %[%r%],", file.stream, context.set.notable, fss_basic_read_delimit_mode_name_all_s, context.set.notable); - fl_print_format(" overrule all other delimit values.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameters %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_columns_s, context.set.notable); - fl_print_format(" and %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, context.set.notable); - fl_print_format(" refer to a Content column.%r", file.stream, f_string_eol_s); - fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", file.stream, f_string_eol_s); - fl_print_format(" This is not to be confused with a depth.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_basic_read_print_help_ - #ifndef _di_fss_basic_read_main_ - f_status_t fss_basic_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_basic_read_main(fll_program_data_t * const main, fss_basic_read_setting_t * const setting) { f_status_t status = F_none; @@ -169,13 +58,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_basic_read_parameter_help_e].result == f_console_result_found_e) { - fss_basic_read_print_help(main->output.to, main->context); + fss_basic_read_print_help(setting, main->message); return status; } if (main->parameters.array[fss_basic_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_basic_read_program_version_s); + fll_program_print_version(main->message, fss_basic_read_program_version_s); return status; } @@ -310,7 +199,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -515,7 +404,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_signal); @@ -581,7 +470,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > fss_basic_read_block_max && fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_basic_read/c/fss_basic_read.h b/level_3/fss_basic_read/c/fss_basic_read.h index aac0e6b..acc481f 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.h +++ b/level_3/fss_basic_read/c/fss_basic_read.h @@ -55,21 +55,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_basic_read_print_help_ - extern f_status_t fss_basic_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_basic_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -82,16 +67,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_basic_read_main_ - extern f_status_t fss_basic_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_basic_read_main(fll_program_data_t * const main, fss_basic_read_setting_t * const setting); #endif // _di_fss_basic_read_main_ #ifdef __cplusplus diff --git a/level_3/fss_basic_read/c/main.c b/level_3/fss_basic_read/c/main.c index ddd1847..33b3e58 100644 --- a/level_3/fss_basic_read/c/main.c +++ b/level_3/fss_basic_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_basic_read_setting_t setting = fss_basic_read_setting_t_initialize; f_console_parameter_t parameters[] = fss_basic_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_basic_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_basic_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_basic_read_setting_load(arguments, &data, &setting); + } + + fss_basic_read_main(&data, &setting); + + fss_basic_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_basic_read/c/print.c b/level_3/fss_basic_read/c/print.c new file mode 100644 index 0000000..13fd2b3 --- /dev/null +++ b/level_3/fss_basic_read/c/print.c @@ -0,0 +1,148 @@ +#include "fss_basic_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_basic_read_print_help_ + f_status_t fss_basic_read_print_help(fss_basic_read_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_basic_read_program_name_long_s, fss_basic_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_basic_read_short_at_s, fss_basic_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(print, fss_basic_read_short_content_s, fss_basic_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); + fll_program_print_help_option(print, fss_basic_read_short_columns_s, fss_basic_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); + fll_program_print_help_option(print, fss_basic_read_short_delimit_s, fss_basic_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); + fll_program_print_help_option(print, fss_basic_read_short_depth_s, fss_basic_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(print, fss_basic_read_short_empty_s, fss_basic_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(print, fss_basic_read_short_line_s, fss_basic_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(print, fss_basic_read_short_name_s, fss_basic_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(print, fss_basic_read_short_object_s, fss_basic_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); + fll_program_print_help_option(print, fss_basic_read_short_pipe_s, fss_basic_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); + fll_program_print_help_option(print, fss_basic_read_short_original_s, fss_basic_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); + fll_program_print_help_option(print, fss_basic_read_short_select_s, fss_basic_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); + fll_program_print_help_option(print, fss_basic_read_short_total_s, fss_basic_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); + fll_program_print_help_option(print, fss_basic_read_short_trim_s, fss_basic_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); + + fll_program_print_help_usage(print, fss_basic_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0000 Basic standard.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", print.to.stream, f_string_eol_s); + fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, print.set->notable, f_string_eol_s); + + fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", print.to.stream, f_string_eol_s); + + fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_at_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", print.to.stream, f_string_eol_s); + fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_object_s, print.set->notable); + fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_total_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_at_s, print.set->notable); + fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_name_s, print.set->notable); + fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_at_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter value.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program may support parameters, such as %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, print.set->notable); + fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, print.set->notable, f_string_eol_s); + fl_print_format(" This is done to help ensure consistency for scripting.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_depth_s, print.set->notable); + fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, print.set->notable); + fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_trim_s, print.set->notable); + fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying both the %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_object_s, print.set->notable); + fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_content_s, print.set->notable, f_string_eol_s); + fl_print_format(" Both the Object and Content printed are already escaped.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Both the Object and Content are separated by a space.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] accepts the following:%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_delimit_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Do not apply delimits.%r", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_none_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_all_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_object_s, print.set->notable, f_string_eol_s); + fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", print.to.stream, f_string_eol_s); + fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_greater_s, print.set->notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_lesser_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_delimit_s, print.set->notable, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_delimit_s, print.set->notable); + fl_print_format(" values %[%r%]", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_none_s, print.set->notable); + fl_print_format(" and %[%r%],", print.to.stream, print.set->notable, fss_basic_read_delimit_mode_name_all_s, print.set->notable); + fl_print_format(" overrule all other delimit values.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameters %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_columns_s, print.set->notable); + fl_print_format(" and %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_read_long_select_s, print.set->notable); + fl_print_format(" refer to a Content column.%r", print.to.stream, f_string_eol_s); + fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This is not to be confused with a depth.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_basic_read_print_help_ + +#ifndef _di_fss_basic_read_print_line_first_ + void fss_basic_read_print_line_first(fss_basic_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_basic_read_print_line_first_ + +#ifndef _di_fss_basic_read_print_line_last_ + void fss_basic_read_print_line_last(fss_basic_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_basic_read_main_flag_verify_e) return; + if ((setting->flag & fss_basic_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_basic_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_basic_read/c/print.h b/level_3/fss_basic_read/c/print.h new file mode 100644 index 0000000..ae20be3 --- /dev/null +++ b/level_3/fss_basic_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_basic_read_print_h +#define _fss_basic_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_read_print_help_ + extern f_status_t fss_basic_read_print_help(fss_basic_read_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_basic_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_read_print_line_first_ + extern void fss_basic_read_print_line_first(fss_basic_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_read_print_line_last_ + extern void fss_basic_read_print_line_last(fss_basic_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_basic_read_print_h diff --git a/level_3/fss_basic_read/c/private-common.c b/level_3/fss_basic_read/c/private-common.c index d89a23a..0bfe454 100644 --- a/level_3/fss_basic_read/c/private-common.c +++ b/level_3/fss_basic_read/c/private-common.c @@ -55,24 +55,6 @@ extern "C" { } #endif // _di_fss_basic_read_depths_resize_ -#ifndef _di_fss_basic_read_print_signal_received_ - void fss_basic_read_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_basic_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_read/c/private-common.h b/level_3/fss_basic_read/c/private-common.h index e942aca..4f8b126 100644 --- a/level_3/fss_basic_read/c/private-common.h +++ b/level_3/fss_basic_read/c/private-common.h @@ -256,16 +256,6 @@ extern "C" { extern f_status_t fss_basic_read_depths_resize(const f_array_length_t length, fss_basic_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_basic_read_depths_resize_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_basic_read_print_signal_received_ - extern void fss_basic_read_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_basic_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_read/c/private-read.c b/level_3/fss_basic_read/c/private-read.c index 28760fc..657a5d4 100644 --- a/level_3/fss_basic_read/c/private-read.c +++ b/level_3/fss_basic_read/c/private-read.c @@ -65,7 +65,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -153,7 +153,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -233,7 +233,7 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_interrupt) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return status; } @@ -378,7 +378,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -461,7 +461,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -494,7 +494,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -645,7 +645,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_basic_read/data/build/settings b/level_3/fss_basic_read/data/build/settings index 081696b..f78b282 100644 --- a/level_3/fss_basic_read/data/build/settings +++ b/level_3/fss_basic_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_basic_read.c common.c private-common.c private-print.c private-read.c +build_sources_library fss_basic_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers fss_basic_read.h common.h +build_sources_headers fss_basic_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_basic_write/c/common.c b/level_3/fss_basic_write/c/common.c index f417c1f..4e4edf1 100644 --- a/level_3/fss_basic_write/c/common.c +++ b/level_3/fss_basic_write/c/common.c @@ -42,6 +42,358 @@ extern "C" { const f_string_static_t fss_basic_write_long_trim_s = macro_f_string_static_t_initialize(FSS_BASIC_WRITE_long_trim_s, 0, FSS_BASIC_WRITE_long_trim_s_length); #endif // _di_fss_basic_write_program_parameters_ +#ifndef _di_fss_basic_write_setting_delete_ + f_status_t fss_basic_write_setting_delete(fss_basic_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_basic_write_setting_delete_ + +#ifndef _di_fss_basic_write_setting_load_ + void fss_basic_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_basic_write_parameter_no_color_e, fss_basic_write_parameter_light_e, fss_basic_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_basic_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_basic_write_parameter_verbosity_quiet_e, fss_basic_write_parameter_verbosity_error_e, fss_basic_write_parameter_verbosity_verbose_e, fss_basic_write_parameter_verbosity_debug_e, fss_basic_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_basic_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_basic_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_basic_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_basic_write_parameter_from_bytesequence_e, fss_basic_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_write_parameter_from_bytesequence_e) { + if (setting->mode & fss_basic_write_mode_from_codepoint_e) { + setting->mode -= fss_basic_write_mode_from_codepoint_e; + } + + setting->mode |= fss_basic_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_write_parameter_from_codepoint_e) { + if (setting->mode & fss_basic_write_mode_from_bytesequence_e) { + setting->mode -= fss_basic_write_mode_from_bytesequence_e; + } + + setting->mode |= fss_basic_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_basic_write_parameter_to_bytesequence_e, fss_basic_write_parameter_to_codepoint_e, fss_basic_write_parameter_to_combining_e, fss_basic_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_basic_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_basic_write_parameter_to_bytesequence_e) { + if (setting->mode & fss_basic_write_mode_to_codepoint_e) { + setting->mode -= fss_basic_write_mode_to_codepoint_e; + } + + if (setting->mode & fss_basic_write_mode_to_combining_e) { + setting->mode -= fss_basic_write_mode_to_combining_e; + } + + if (setting->mode & fss_basic_write_mode_to_width_e) { + setting->mode -= fss_basic_write_mode_to_width_e; + } + + setting->mode |= fss_basic_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_basic_write_parameter_to_codepoint_e) { + if (setting->mode & fss_basic_write_mode_to_bytesequence_e) { + setting->mode -= fss_basic_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_write_mode_to_combining_e) { + setting->mode -= fss_basic_write_mode_to_combining_e; + } + + if (setting->mode & fss_basic_write_mode_to_width_e) { + setting->mode -= fss_basic_write_mode_to_width_e; + } + + setting->mode |= fss_basic_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_basic_write_parameter_to_combining_e) { + if (setting->mode & fss_basic_write_mode_to_bytesequence_e) { + setting->mode -= fss_basic_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_write_mode_to_codepoint_e) { + setting->mode -= fss_basic_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_write_mode_to_width_e; + } + + setting->mode |= fss_basic_write_mode_to_combining_e; + } + else if (choices.array[choice] == fss_basic_write_parameter_to_width_e) { + if (setting->mode & fss_basic_write_mode_to_bytesequence_e) { + setting->mode -= fss_basic_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_basic_write_mode_to_codepoint_e) { + setting->mode -= fss_basic_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_basic_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_basic_write_mode_to_combining_e; + } + + setting->mode |= fss_basic_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_basic_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_basic_write_parameter_to_file_e].values.used > 1) { + fss_basic_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_basic_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_basic_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_basic_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_basic_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_basic_write_main_flag_file_to_e; + } + else { + fss_basic_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_basic_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_basic_write_parameter_to_file_e].result == f_console_result_found_e) { + fss_basic_write_print_error_no_value(main, setting, fss_basic_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_basic_write_main_flag_file_to_e) { + setting->flag -= fss_basic_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_basic_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_basic_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_basic_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_basic_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_basic_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_basic_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_basic_write_main_flag_file_from_e; + } + else if (main->parameters.array[fss_basic_write_parameter_from_file_e].result == f_console_result_found_e) { + fss_basic_write_print_error_no_value(main, setting, fss_basic_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_basic_write_main_flag_file_from_e) { + setting->flag -= fss_basic_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_basic_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_basic_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_basic_write_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_basic_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_basic_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_basic_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_basic_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_write_main_flag_header_e; + } + + if (main->parameters.array[fss_basic_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_write_main_flag_separate_e; + } + + if (main->parameters.array[fss_basic_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_basic_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_basic_write_setting_load_ + +#ifndef _di_fss_basic_write_setting_unload_ + f_status_t fss_basic_write_setting_unload(fll_program_data_t * const main, fss_basic_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_basic_write_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_basic_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/c/common.h b/level_3/fss_basic_write/c/common.h index c0764f4..1654873 100644 --- a/level_3/fss_basic_write/c/common.h +++ b/level_3/fss_basic_write/c/common.h @@ -208,6 +208,132 @@ extern "C" { #define fss_basic_write_total_parameters_d 20 #endif // _di_fss_basic_write_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_basic_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_basic_write_main_flag_e_ + enum { + fss_basic_write_main_flag_none_e = 0x0, + fss_basic_write_main_flag_file_from_e = 0x1, + fss_basic_write_main_flag_file_to_e = 0x2, + fss_basic_write_main_flag_header_e = 0x4, + fss_basic_write_main_flag_help_e = 0x8, + fss_basic_write_main_flag_separate_e = 0x10, + fss_basic_write_main_flag_strip_invalid_e = 0x20, + fss_basic_write_main_flag_verify_e = 0x40, + fss_basic_write_main_flag_version_e = 0x80, + }; +#endif // _di_fss_basic_write_main_flag_e_ + +/** + * The fss basic write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_basic_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_basic_write_setting_t; + + #define fss_basic_write_setting_t_initialize \ + { \ + fss_basic_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_basic_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_basic_write_setting_delete_ + extern f_status_t fss_basic_write_setting_delete(fss_basic_write_setting_t * const setting); +#endif // _di_fss_basic_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_basic_write_setting_load_ + extern void fss_basic_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_basic_write_setting_t * const setting); +#endif // _di_fss_basic_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_basic_write_setting_unload_ + extern f_status_t fss_basic_write_setting_unload(fll_program_data_t * const main, fss_basic_write_setting_t * const setting); +#endif // _di_fss_basic_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/c/fss_basic_write.c b/level_3/fss_basic_write/c/fss_basic_write.c index 448fdd6..b375bb6 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.c +++ b/level_3/fss_basic_write/c/fss_basic_write.c @@ -6,59 +6,8 @@ extern "C" { #endif -#ifndef _di_fss_basic_write_print_help_ - f_status_t fss_basic_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_basic_write_program_name_long_s, fss_basic_write_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_basic_write_short_file_s, fss_basic_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, fss_basic_write_short_content_s, fss_basic_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, fss_basic_write_short_double_s, fss_basic_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, fss_basic_write_short_ignore_s, fss_basic_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); - fll_program_print_help_option(file, context, fss_basic_write_short_object_s, fss_basic_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, fss_basic_write_short_partial_s, fss_basic_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); - fll_program_print_help_option(file, context, fss_basic_write_short_prepend_s, fss_basic_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); - fll_program_print_help_option(file, context, fss_basic_write_short_single_s, fss_basic_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - fll_program_print_help_option(file, context, fss_basic_write_short_trim_s, fss_basic_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); - - fll_program_print_help_usage(file, context, fss_basic_write_program_name_s, f_string_empty_s); - - fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", file.stream, f_string_eol_s, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The FSS-0000 (Basic) specification does not support multi-line Content, therefore the parameter '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_write_long_prepend_s, context.set.notable); - fl_print_format(" does nothing.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_basic_write_long_ignore_s, context.set.notable, f_string_eol_s); - fl_print_format(" This parameter requires two values.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_basic_write_print_help_ - #ifndef _di_fss_basic_write_main_ - f_status_t fss_basic_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_basic_write_main(fll_program_data_t * const main, fss_basic_write_setting_t * const setting) { f_status_t status = F_none; @@ -110,13 +59,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_basic_write_parameter_help_e].result == f_console_result_found_e) { - fss_basic_write_print_help(main->output.to, main->context); + fss_basic_write_print_help(setting, main->message); return status; } if (main->parameters.array[fss_basic_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_basic_write_program_version_s); + fll_program_print_version(main->message, fss_basic_write_program_version_s); return status; } @@ -405,7 +354,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -424,7 +373,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -444,7 +393,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_basic_write/c/fss_basic_write.h b/level_3/fss_basic_write/c/fss_basic_write.h index 21d11c9..f9b3294 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.h +++ b/level_3/fss_basic_write/c/fss_basic_write.h @@ -48,21 +48,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_basic_write_print_help_ - extern f_status_t fss_basic_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_basic_write_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -83,7 +68,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_basic_write_main_ - extern f_status_t fss_basic_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_basic_write_main(fll_program_data_t * const main, fss_basic_write_setting_t * const setting); #endif // _di_fss_basic_write_main_ #ifdef __cplusplus diff --git a/level_3/fss_basic_write/c/main.c b/level_3/fss_basic_write/c/main.c index 0c1a9a5..c953bc5 100644 --- a/level_3/fss_basic_write/c/main.c +++ b/level_3/fss_basic_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_basic_write_setting_t setting = fss_basic_write_setting_t_initialize; f_console_parameter_t parameters[] = fss_basic_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_basic_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_basic_write_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_basic_write_setting_load(arguments, &data, &setting); + } + + fss_basic_write_main(&data, &setting); + + fss_basic_write_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_basic_write/c/print.c b/level_3/fss_basic_write/c/print.c new file mode 100644 index 0000000..9cd5a00 --- /dev/null +++ b/level_3/fss_basic_write/c/print.c @@ -0,0 +1,88 @@ +#include "fss_basic_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_basic_write_print_help_ + f_status_t fss_basic_write_print_help(fss_basic_write_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_basic_write_program_name_long_s, fss_basic_write_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_basic_write_short_file_s, fss_basic_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, fss_basic_write_short_content_s, fss_basic_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, fss_basic_write_short_double_s, fss_basic_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, fss_basic_write_short_ignore_s, fss_basic_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); + fll_program_print_help_option(print, fss_basic_write_short_object_s, fss_basic_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, fss_basic_write_short_partial_s, fss_basic_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); + fll_program_print_help_option(print, fss_basic_write_short_prepend_s, fss_basic_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); + fll_program_print_help_option(print, fss_basic_write_short_single_s, fss_basic_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + fll_program_print_help_option(print, fss_basic_write_short_trim_s, fss_basic_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); + + fll_program_print_help_usage(print, fss_basic_write_program_name_s, f_string_empty_s); + + fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", print.to.stream, f_string_eol_s, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The FSS-0000 (Basic) specification does not support multi-line Content, therefore the parameter '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_write_long_prepend_s, print.set->notable); + fl_print_format(" does nothing.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_basic_write_long_ignore_s, print.set->notable, f_string_eol_s); + fl_print_format(" This parameter requires two values.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_basic_write_print_help_ + +#ifndef _di_fss_basic_write_print_line_first_ + void fss_basic_write_print_line_first(fss_basic_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_basic_write_print_line_first_ + +#ifndef _di_fss_basic_write_print_line_last_ + void fss_basic_write_print_line_last(fss_basic_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_basic_write_main_flag_verify_e) return; + if ((setting->flag & fss_basic_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_basic_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_basic_write/c/print.h b/level_3/fss_basic_write/c/print.h new file mode 100644 index 0000000..99ef649 --- /dev/null +++ b/level_3/fss_basic_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_basic_write_print_h +#define _fss_basic_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_basic_write_print_help_ + extern f_status_t fss_basic_write_print_help(fss_basic_write_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_basic_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_write_print_line_first_ + extern void fss_basic_write_print_line_first(fss_basic_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_basic_write_print_line_last_ + extern void fss_basic_write_print_line_last(fss_basic_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_basic_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_basic_write_print_h diff --git a/level_3/fss_basic_write/c/private-common.c b/level_3/fss_basic_write/c/private-common.c index f3fb15e..d1c0ac4 100644 --- a/level_3/fss_basic_write/c/private-common.c +++ b/level_3/fss_basic_write/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_basic_write_print_signal_received_ - void fss_basic_write_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_basic_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/c/private-common.h b/level_3/fss_basic_write/c/private-common.h index 972ecdc..c9af824 100644 --- a/level_3/fss_basic_write/c/private-common.h +++ b/level_3/fss_basic_write/c/private-common.h @@ -24,16 +24,6 @@ extern "C" { #define fss_basic_write_common_allocation_small_d 128 #endif // _di_fss_basic_write_common_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_basic_write_print_signal_received_ - extern void fss_basic_write_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_basic_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_basic_write/c/private-write.c b/level_3/fss_basic_write/c/private-write.c index 9c5c7f3..d86cd5f 100644 --- a/level_3/fss_basic_write/c/private-write.c +++ b/level_3/fss_basic_write/c/private-write.c @@ -168,7 +168,7 @@ extern "C" { if (!((++main->signal_check) % fss_basic_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_basic_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_basic_write/data/build/settings b/level_3/fss_basic_write/data/build/settings index 12f0637..292c290 100644 --- a/level_3/fss_basic_write/data/build/settings +++ b/level_3/fss_basic_write/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_basic_write.c common.c private-common.c private-write.c +build_sources_library fss_basic_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers fss_basic_write.h common.h +build_sources_headers fss_basic_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_embedded_list_read/c/common.c b/level_3/fss_embedded_list_read/c/common.c index d93b633..98a5025 100644 --- a/level_3/fss_embedded_list_read/c/common.c +++ b/level_3/fss_embedded_list_read/c/common.c @@ -59,6 +59,358 @@ extern "C" { const f_string_static_t fss_embedded_list_read_delimit_mode_name_lesser_s = macro_f_string_static_t_initialize(FSS_EMBEDDED_LIST_READ_delimit_mode_name_lesser_s, 0, FSS_EMBEDDED_LIST_READ_delimit_mode_name_lesser_s_length); #endif // _di_fss_embedded_list_read_delimit_mode_ +#ifndef _di_fss_embedded_list_read_setting_delete_ + f_status_t fss_embedded_list_read_setting_delete(fss_embedded_list_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_embedded_list_read_setting_delete_ + +#ifndef _di_fss_embedded_list_read_setting_load_ + void fss_embedded_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_embedded_list_read_parameter_no_color_e, fss_embedded_list_read_parameter_light_e, fss_embedded_list_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_embedded_list_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_embedded_list_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_embedded_list_read_parameter_verbosity_quiet_e, fss_embedded_list_read_parameter_verbosity_error_e, fss_embedded_list_read_parameter_verbosity_verbose_e, fss_embedded_list_read_parameter_verbosity_debug_e, fss_embedded_list_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_embedded_list_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_embedded_list_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_embedded_list_read_parameter_from_bytesequence_e, fss_embedded_list_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_embedded_list_read_parameter_from_bytesequence_e) { + if (setting->mode & fss_embedded_list_read_mode_from_codepoint_e) { + setting->mode -= fss_embedded_list_read_mode_from_codepoint_e; + } + + setting->mode |= fss_embedded_list_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_embedded_list_read_parameter_from_codepoint_e) { + if (setting->mode & fss_embedded_list_read_mode_from_bytesequence_e) { + setting->mode -= fss_embedded_list_read_mode_from_bytesequence_e; + } + + setting->mode |= fss_embedded_list_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_embedded_list_read_parameter_to_bytesequence_e, fss_embedded_list_read_parameter_to_codepoint_e, fss_embedded_list_read_parameter_to_combining_e, fss_embedded_list_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_embedded_list_read_parameter_to_bytesequence_e) { + if (setting->mode & fss_embedded_list_read_mode_to_codepoint_e) { + setting->mode -= fss_embedded_list_read_mode_to_codepoint_e; + } + + if (setting->mode & fss_embedded_list_read_mode_to_combining_e) { + setting->mode -= fss_embedded_list_read_mode_to_combining_e; + } + + if (setting->mode & fss_embedded_list_read_mode_to_width_e) { + setting->mode -= fss_embedded_list_read_mode_to_width_e; + } + + setting->mode |= fss_embedded_list_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_embedded_list_read_parameter_to_codepoint_e) { + if (setting->mode & fss_embedded_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_embedded_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_embedded_list_read_mode_to_combining_e) { + setting->mode -= fss_embedded_list_read_mode_to_combining_e; + } + + if (setting->mode & fss_embedded_list_read_mode_to_width_e) { + setting->mode -= fss_embedded_list_read_mode_to_width_e; + } + + setting->mode |= fss_embedded_list_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_embedded_list_read_parameter_to_combining_e) { + if (setting->mode & fss_embedded_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_embedded_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_embedded_list_read_mode_to_codepoint_e) { + setting->mode -= fss_embedded_list_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_embedded_list_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_embedded_list_read_mode_to_width_e; + } + + setting->mode |= fss_embedded_list_read_mode_to_combining_e; + } + else if (choices.array[choice] == fss_embedded_list_read_parameter_to_width_e) { + if (setting->mode & fss_embedded_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_embedded_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_embedded_list_read_mode_to_codepoint_e) { + setting->mode -= fss_embedded_list_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_embedded_list_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_embedded_list_read_mode_to_combining_e; + } + + setting->mode |= fss_embedded_list_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_embedded_list_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_embedded_list_read_parameter_to_file_e].values.used > 1) { + fss_embedded_list_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_embedded_list_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_embedded_list_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_embedded_list_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_embedded_list_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_embedded_list_read_main_flag_file_to_e; + } + else { + fss_embedded_list_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_embedded_list_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_embedded_list_read_parameter_to_file_e].result == f_console_result_found_e) { + fss_embedded_list_read_print_error_no_value(main, setting, fss_embedded_list_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_embedded_list_read_main_flag_file_to_e) { + setting->flag -= fss_embedded_list_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_embedded_list_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_embedded_list_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_embedded_list_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_embedded_list_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_embedded_list_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_embedded_list_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_embedded_list_read_main_flag_file_from_e; + } + else if (main->parameters.array[fss_embedded_list_read_parameter_from_file_e].result == f_console_result_found_e) { + fss_embedded_list_read_print_error_no_value(main, setting, fss_embedded_list_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_embedded_list_read_main_flag_file_from_e) { + setting->flag -= fss_embedded_list_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_embedded_list_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_embedded_list_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_embedded_list_read_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_embedded_list_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_embedded_list_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_embedded_list_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_embedded_list_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_read_main_flag_header_e; + } + + if (main->parameters.array[fss_embedded_list_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_read_main_flag_separate_e; + } + + if (main->parameters.array[fss_embedded_list_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_embedded_list_read_setting_load_ + +#ifndef _di_fss_embedded_list_read_setting_unload_ + f_status_t fss_embedded_list_read_setting_unload(fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_embedded_list_read_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_embedded_list_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_read/c/common.h b/level_3/fss_embedded_list_read/c/common.h index 70f025a..bf62570 100644 --- a/level_3/fss_embedded_list_read/c/common.h +++ b/level_3/fss_embedded_list_read/c/common.h @@ -276,6 +276,132 @@ extern "C" { }; #endif // _di_fss_embedded_list_read_delimit_modes_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_embedded_list_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_embedded_list_read_main_flag_e_ + enum { + fss_embedded_list_read_main_flag_none_e = 0x0, + fss_embedded_list_read_main_flag_file_from_e = 0x1, + fss_embedded_list_read_main_flag_file_to_e = 0x2, + fss_embedded_list_read_main_flag_header_e = 0x4, + fss_embedded_list_read_main_flag_help_e = 0x8, + fss_embedded_list_read_main_flag_separate_e = 0x10, + fss_embedded_list_read_main_flag_strip_invalid_e = 0x20, + fss_embedded_list_read_main_flag_verify_e = 0x40, + fss_embedded_list_read_main_flag_version_e = 0x80, + }; +#endif // _di_fss_embedded_list_read_main_flag_e_ + +/** + * The fss embedded list read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_embedded_list_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_embedded_list_read_setting_t; + + #define fss_embedded_list_read_setting_t_initialize \ + { \ + fss_embedded_list_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_embedded_list_read_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_embedded_list_read_setting_delete_ + extern f_status_t fss_embedded_list_read_setting_delete(fss_embedded_list_read_setting_t * const setting); +#endif // _di_fss_embedded_list_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_embedded_list_read_setting_load_ + extern void fss_embedded_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting); +#endif // _di_fss_embedded_list_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_embedded_list_read_setting_unload_ + extern f_status_t fss_embedded_list_read_setting_unload(fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting); +#endif // _di_fss_embedded_list_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c index 3eb1dba..e8d4762 100644 --- a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c +++ b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.c @@ -7,118 +7,8 @@ extern "C" { #endif -#ifndef _di_fss_embedded_list_read_print_help_ - f_status_t fss_embedded_list_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_embedded_list_read_program_name_long_s, fss_embedded_list_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_embedded_list_read_short_at_s, fss_embedded_list_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_content_s, fss_embedded_list_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_columns_s, fss_embedded_list_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_delimit_s, fss_embedded_list_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_depth_s, fss_embedded_list_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_empty_s, fss_embedded_list_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_line_s, fss_embedded_list_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_name_s, fss_embedded_list_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_object_s, fss_embedded_list_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_pipe_s, fss_embedded_list_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_original_s, fss_embedded_list_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_select_s, fss_embedded_list_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_total_s, fss_embedded_list_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(file, context, fss_embedded_list_read_short_trim_s, fss_embedded_list_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); - - fll_program_print_help_usage(file, context, fss_embedded_list_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0008 Embedded List standard.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", file.stream, f_string_eol_s); - fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, context.set.notable, f_string_eol_s); - - fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", file.stream, f_string_eol_s); - - fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_at_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", file.stream, f_string_eol_s); - fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_object_s, context.set.notable); - fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_total_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_at_s, context.set.notable); - fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_name_s, context.set.notable); - fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_at_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter value.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program may support parameters, such as %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, context.set.notable); - fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, context.set.notable, f_string_eol_s); - fl_print_format(" This is done to help ensure consistency for scripting.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, context.set.notable); - fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", file.stream, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, context.set.notable); - fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_trim_s, context.set.notable); - fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying both the %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_object_s, context.set.notable); - fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_content_s, context.set.notable, f_string_eol_s); - fl_print_format(" Both the Object and Content printed are already escaped.%r", file.stream, f_string_eol_s); - fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] accepts the following:%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_delimit_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Do not apply delimits.%r", file.stream, context.set.notable, fss_embedded_list_read_delimit_mode_name_none_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", file.stream, context.set.notable, fss_embedded_list_read_delimit_mode_name_all_s, context.set.notable, f_string_eol_s); - fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", file.stream, f_string_eol_s); - fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", file.stream, context.set.notable, fss_embedded_list_read_delimit_mode_name_greater_s, context.set.notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", file.stream, context.set.notable, fss_embedded_list_read_delimit_mode_name_lesser_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_delimit_s, context.set.notable, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_delimit_s, context.set.notable); - fl_print_format(" values %[%r%]", file.stream, context.set.notable, fss_embedded_list_read_delimit_mode_name_none_s, context.set.notable); - fl_print_format(" and %[%r%],", file.stream, context.set.notable, fss_embedded_list_read_delimit_mode_name_all_s, context.set.notable); - fl_print_format(" overrule all other delimit values.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameters %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_columns_s, context.set.notable); - fl_print_format(" and %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, context.set.notable); - fl_print_format(" refer to a Content column.%r", file.stream, f_string_eol_s); - fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", file.stream, f_string_eol_s); - fl_print_format(" This is not to be confused with a depth.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_embedded_list_read_print_help_ - #ifndef _di_fss_embedded_list_read_main_ - f_status_t fss_embedded_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_embedded_list_read_main(fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting) { f_status_t status = F_none; @@ -172,7 +62,7 @@ extern "C" { status = F_none; if (main->parameters.array[fss_embedded_list_read_parameter_help_e].result == f_console_result_found_e) { - fss_embedded_list_read_print_help(main->output.to, main->context); + fss_embedded_list_read_print_help(setting, main->message); fss_embedded_list_read_data_delete(&data); @@ -180,7 +70,7 @@ extern "C" { } if (main->parameters.array[fss_embedded_list_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_embedded_list_read_program_version_s); + fll_program_print_version(main->message, fss_embedded_list_read_program_version_s); fss_embedded_list_read_data_delete(&data); @@ -402,7 +292,7 @@ extern "C" { if (!((++main->signal_check) % fss_embedded_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_embedded_list_read_print_signal_received(&data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -477,7 +367,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > fss_embedded_list_read_block_max && fll_program_standard_signal_received(main)) { - fss_embedded_list_read_print_signal_received(&data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h index f6e853d..0145067 100644 --- a/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h +++ b/level_3/fss_embedded_list_read/c/fss_embedded_list_read.h @@ -55,21 +55,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_embedded_list_read_print_help_ - extern f_status_t fss_embedded_list_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_embedded_list_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -82,16 +67,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_embedded_list_read_main_ - extern f_status_t fss_embedded_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_embedded_list_read_main(fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting); #endif // _di_fss_embedded_list_read_main_ #ifdef __cplusplus diff --git a/level_3/fss_embedded_list_read/c/main.c b/level_3/fss_embedded_list_read/c/main.c index fa84dae..db1288b 100644 --- a/level_3/fss_embedded_list_read/c/main.c +++ b/level_3/fss_embedded_list_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_extended_list_read_setting_t setting = fss_extended_list_read_setting_t_initialize; f_console_parameter_t parameters[] = fss_embedded_list_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_embedded_list_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_embedded_list_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_embedded_list_read_setting_load(arguments, &data, &setting); + } + + fss_embedded_list_read_main(&data, &setting); + + fss_embedded_list_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_embedded_list_read/c/print.c b/level_3/fss_embedded_list_read/c/print.c new file mode 100644 index 0000000..1311924 --- /dev/null +++ b/level_3/fss_embedded_list_read/c/print.c @@ -0,0 +1,147 @@ +#include "fss_embedded_list_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_embedded_list_read_print_help_ + f_status_t fss_embedded_list_read_print_help(fss_embedded_list_read_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_embedded_list_read_program_name_long_s, fss_embedded_list_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_embedded_list_read_short_at_s, fss_embedded_list_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(print, fss_embedded_list_read_short_content_s, fss_embedded_list_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); + fll_program_print_help_option(print, fss_embedded_list_read_short_columns_s, fss_embedded_list_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); + fll_program_print_help_option(print, fss_embedded_list_read_short_delimit_s, fss_embedded_list_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); + fll_program_print_help_option(print, fss_embedded_list_read_short_depth_s, fss_embedded_list_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(print, fss_embedded_list_read_short_empty_s, fss_embedded_list_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(print, fss_embedded_list_read_short_line_s, fss_embedded_list_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(print, fss_embedded_list_read_short_name_s, fss_embedded_list_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(print, fss_embedded_list_read_short_object_s, fss_embedded_list_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); + fll_program_print_help_option(print, fss_embedded_list_read_short_pipe_s, fss_embedded_list_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); + fll_program_print_help_option(print, fss_embedded_list_read_short_original_s, fss_embedded_list_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); + fll_program_print_help_option(print, fss_embedded_list_read_short_select_s, fss_embedded_list_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); + fll_program_print_help_option(print, fss_embedded_list_read_short_total_s, fss_embedded_list_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); + fll_program_print_help_option(print, fss_embedded_list_read_short_trim_s, fss_embedded_list_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); + + fll_program_print_help_usage(print, fss_embedded_list_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0008 Embedded List standard.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", print.to.stream, f_string_eol_s); + fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, print.set->notable, f_string_eol_s); + + fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", print.to.stream, f_string_eol_s); + + fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_at_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", print.to.stream, f_string_eol_s); + fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_object_s, print.set->notable); + fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_total_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_at_s, print.set->notable); + fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_name_s, print.set->notable); + fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_at_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter value.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program may support parameters, such as %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, print.set->notable); + fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, print.set->notable, f_string_eol_s); + fl_print_format(" This is done to help ensure consistency for scripting.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_depth_s, print.set->notable); + fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, print.set->notable); + fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_trim_s, print.set->notable); + fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying both the %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_object_s, print.set->notable); + fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_content_s, print.set->notable, f_string_eol_s); + fl_print_format(" Both the Object and Content printed are already escaped.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] accepts the following:%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_delimit_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Do not apply delimits.%r", print.to.stream, print.set->notable, fss_embedded_list_read_delimit_mode_name_none_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", print.to.stream, print.set->notable, fss_embedded_list_read_delimit_mode_name_all_s, print.set->notable, f_string_eol_s); + fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", print.to.stream, f_string_eol_s); + fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", print.to.stream, print.set->notable, fss_embedded_list_read_delimit_mode_name_greater_s, print.set->notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", print.to.stream, print.set->notable, fss_embedded_list_read_delimit_mode_name_lesser_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_delimit_s, print.set->notable, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_delimit_s, print.set->notable); + fl_print_format(" values %[%r%]", print.to.stream, print.set->notable, fss_embedded_list_read_delimit_mode_name_none_s, print.set->notable); + fl_print_format(" and %[%r%],", print.to.stream, print.set->notable, fss_embedded_list_read_delimit_mode_name_all_s, print.set->notable); + fl_print_format(" overrule all other delimit values.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameters %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_columns_s, print.set->notable); + fl_print_format(" and %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_read_long_select_s, print.set->notable); + fl_print_format(" refer to a Content column.%r", print.to.stream, f_string_eol_s); + fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This is not to be confused with a depth.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_embedded_list_read_print_help_ + +#ifndef _di_fss_embedded_list_read_print_line_first_ + void fss_embedded_list_read_print_line_first(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_embedded_list_read_print_line_first_ + +#ifndef _di_fss_embedded_list_read_print_line_last_ + void fss_embedded_list_read_print_line_last(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_embedded_list_read_main_flag_verify_e) return; + if ((setting->flag & fss_embedded_list_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_embedded_list_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_embedded_list_read/c/print.h b/level_3/fss_embedded_list_read/c/print.h new file mode 100644 index 0000000..4787541 --- /dev/null +++ b/level_3/fss_embedded_list_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_embedded_list_read_print_h +#define _fss_embedded_list_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_embedded_list_read_print_help_ + extern f_status_t fss_embedded_list_read_print_help(fss_embedded_list_read_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_embedded_list_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_read_print_line_first_ + extern void fss_embedded_list_read_print_line_first(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_read_print_line_last_ + extern void fss_embedded_list_read_print_line_last(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_embedded_list_read_print_h diff --git a/level_3/fss_embedded_list_read/c/private-common.c b/level_3/fss_embedded_list_read/c/private-common.c index f11d776..ddc05e2 100644 --- a/level_3/fss_embedded_list_read/c/private-common.c +++ b/level_3/fss_embedded_list_read/c/private-common.c @@ -48,24 +48,6 @@ extern "C" { } #endif // _di_fss_embedded_list_read_depths_resize_ -#ifndef _di_fss_embedded_list_read_print_signal_received_ - void fss_embedded_list_read_print_signal_received(fss_embedded_list_read_data_t * const data) { - - if (data->main->warning.verbosity != f_console_verbosity_verbose_e && data->main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(data->main->warning.to.stream); - - flockfile(data->main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", data->main->warning.to.stream, data->main->context.set.reset, f_string_eol_s, f_string_eol_s, data->main->context.set.warning, data->main->context.set.warning); - fl_print_format("%[%i%]", data->main->warning.to.stream, data->main->context.set.notable, data->main->signal_received, data->main->context.set.notable); - fl_print_format("%[.%]%r", data->main->warning.to.stream, data->main->context.set.warning, data->main->context.set.warning, f_string_eol_s); - - funlockfile(data->main->warning.to.stream); - } -#endif // _di_fss_embedded_list_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_read/c/private-common.h b/level_3/fss_embedded_list_read/c/private-common.h index 30ef143..b673ccc 100644 --- a/level_3/fss_embedded_list_read/c/private-common.h +++ b/level_3/fss_embedded_list_read/c/private-common.h @@ -209,16 +209,6 @@ extern "C" { extern f_status_t fss_embedded_list_read_depths_resize(const f_array_length_t length, fss_embedded_list_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_embedded_list_read_depths_resize_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param data - * The program data. - */ -#ifndef _di_fss_embedded_list_read_print_signal_received_ - extern void fss_embedded_list_read_print_signal_received(fss_embedded_list_read_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_fss_embedded_list_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_read/c/private-read.c b/level_3/fss_embedded_list_read/c/private-read.c index c013d58..3bf2ca3 100644 --- a/level_3/fss_embedded_list_read/c/private-read.c +++ b/level_3/fss_embedded_list_read/c/private-read.c @@ -131,7 +131,7 @@ extern "C" { if (!((++data->main->signal_check) % fss_embedded_list_read_signal_check_d)) { if (fll_program_standard_signal_received(data->main)) { - fss_embedded_list_read_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -556,7 +556,7 @@ extern "C" { if (!((++data->main->signal_check) % fss_embedded_list_read_signal_check_d)) { if (fll_program_standard_signal_received(data->main)) { - fss_embedded_list_read_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_embedded_list_read/data/build/settings b/level_3/fss_embedded_list_read/data/build/settings index d00cd46..ef09d6b 100644 --- a/level_3/fss_embedded_list_read/data/build/settings +++ b/level_3/fss_embedded_list_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_embedded_list_read.c common.c private-common.c private-print.c private-read.c +build_sources_library fss_embedded_list_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers fss_embedded_list_read.h common.h +build_sources_headers fss_embedded_list_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_embedded_list_write/c/common.c b/level_3/fss_embedded_list_write/c/common.c index 9a528ee..a31b4b7 100644 --- a/level_3/fss_embedded_list_write/c/common.c +++ b/level_3/fss_embedded_list_write/c/common.c @@ -42,6 +42,358 @@ extern "C" { const f_string_static_t fss_embedded_list_write_long_trim_s = macro_f_string_static_t_initialize(FSS_EMBEDDED_LIST_WRITE_long_trim_s, 0, FSS_EMBEDDED_LIST_WRITE_long_trim_s_length); #endif // _di_fss_embedded_list_write_parameters_ +#ifndef _di_fss_embedded_list_write_setting_delete_ + f_status_t fss_embedded_list_write_setting_delete(fss_embedded_list_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_embedded_list_write_setting_delete_ + +#ifndef _di_fss_embedded_list_write_setting_load_ + void fss_embedded_list_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_embedded_list_write_parameter_no_color_e, fss_embedded_list_write_parameter_light_e, fss_embedded_list_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_embedded_list_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_embedded_list_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_embedded_list_write_parameter_verbosity_quiet_e, fss_embedded_list_write_parameter_verbosity_error_e, fss_embedded_list_write_parameter_verbosity_verbose_e, fss_embedded_list_write_parameter_verbosity_debug_e, fss_embedded_list_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_embedded_list_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_embedded_list_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_embedded_list_write_parameter_from_bytesequence_e, fss_embedded_list_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_embedded_list_write_parameter_from_bytesequence_e) { + if (setting->mode & fss_embedded_list_write_mode_from_codepoint_e) { + setting->mode -= fss_embedded_list_write_mode_from_codepoint_e; + } + + setting->mode |= fss_embedded_list_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_embedded_list_write_parameter_from_codepoint_e) { + if (setting->mode & fss_embedded_list_write_mode_from_bytesequence_e) { + setting->mode -= fss_embedded_list_write_mode_from_bytesequence_e; + } + + setting->mode |= fss_embedded_list_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_embedded_list_write_parameter_to_bytesequence_e, fss_embedded_list_write_parameter_to_codepoint_e, fss_embedded_list_write_parameter_to_combining_e, fss_embedded_list_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_embedded_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_embedded_list_write_parameter_to_bytesequence_e) { + if (setting->mode & fss_embedded_list_write_mode_to_codepoint_e) { + setting->mode -= fss_embedded_list_write_mode_to_codepoint_e; + } + + if (setting->mode & fss_embedded_list_write_mode_to_combining_e) { + setting->mode -= fss_embedded_list_write_mode_to_combining_e; + } + + if (setting->mode & fss_embedded_list_write_mode_to_width_e) { + setting->mode -= fss_embedded_list_write_mode_to_width_e; + } + + setting->mode |= fss_embedded_list_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_embedded_list_write_parameter_to_codepoint_e) { + if (setting->mode & fss_embedded_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_embedded_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_embedded_list_write_mode_to_combining_e) { + setting->mode -= fss_embedded_list_write_mode_to_combining_e; + } + + if (setting->mode & fss_embedded_list_write_mode_to_width_e) { + setting->mode -= fss_embedded_list_write_mode_to_width_e; + } + + setting->mode |= fss_embedded_list_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_embedded_list_write_parameter_to_combining_e) { + if (setting->mode & fss_embedded_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_embedded_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_embedded_list_write_mode_to_codepoint_e) { + setting->mode -= fss_embedded_list_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_embedded_list_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_embedded_list_write_mode_to_width_e; + } + + setting->mode |= fss_embedded_list_write_mode_to_combining_e; + } + else if (choices.array[choice] == fss_embedded_list_write_parameter_to_width_e) { + if (setting->mode & fss_embedded_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_embedded_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_embedded_list_write_mode_to_codepoint_e) { + setting->mode -= fss_embedded_list_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_embedded_list_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_embedded_list_write_mode_to_combining_e; + } + + setting->mode |= fss_embedded_list_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_embedded_list_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_embedded_list_write_parameter_to_file_e].values.used > 1) { + fss_embedded_list_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_embedded_list_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_embedded_list_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_embedded_list_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_embedded_list_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_embedded_list_write_main_flag_file_to_e; + } + else { + fss_embedded_list_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_embedded_list_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_embedded_list_write_parameter_to_file_e].result == f_console_result_found_e) { + fss_embedded_list_write_print_error_no_value(main, setting, fss_embedded_list_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_embedded_list_write_main_flag_file_to_e) { + setting->flag -= fss_embedded_list_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_embedded_list_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_embedded_list_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_embedded_list_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_embedded_list_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_embedded_list_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_embedded_list_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_embedded_list_write_main_flag_file_from_e; + } + else if (main->parameters.array[fss_embedded_list_write_parameter_from_file_e].result == f_console_result_found_e) { + fss_embedded_list_write_print_error_no_value(main, setting, fss_embedded_list_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_embedded_list_write_main_flag_file_from_e) { + setting->flag -= fss_embedded_list_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_embedded_list_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_embedded_list_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_embedded_list_write_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_embedded_list_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_embedded_list_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_embedded_list_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_embedded_list_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_write_main_flag_header_e; + } + + if (main->parameters.array[fss_embedded_list_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_write_main_flag_separate_e; + } + + if (main->parameters.array[fss_embedded_list_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_embedded_list_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_embedded_list_write_setting_load_ + +#ifndef _di_fss_embedded_list_write_setting_unload_ + f_status_t fss_embedded_list_write_setting_unload(fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_embedded_list_write_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_embedded_list_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_write/c/common.h b/level_3/fss_embedded_list_write/c/common.h index 6351e65..2e0c4c8 100644 --- a/level_3/fss_embedded_list_write/c/common.h +++ b/level_3/fss_embedded_list_write/c/common.h @@ -208,6 +208,132 @@ extern "C" { #define fss_embedded_list_write_total_parameters_d 21 #endif // _di_fss_embedded_list_write_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_embedded_list_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_embedded_list_write_main_flag_e_ + enum { + fss_embedded_list_write_main_flag_none_e = 0x0, + fss_embedded_list_write_main_flag_file_from_e = 0x1, + fss_embedded_list_write_main_flag_file_to_e = 0x2, + fss_embedded_list_write_main_flag_header_e = 0x4, + fss_embedded_list_write_main_flag_help_e = 0x8, + fss_embedded_list_write_main_flag_separate_e = 0x10, + fss_embedded_list_write_main_flag_strip_invalid_e = 0x20, + fss_embedded_list_write_main_flag_verify_e = 0x40, + fss_embedded_list_write_main_flag_version_e = 0x80, + }; +#endif // _di_fss_embedded_list_write_main_flag_e_ + +/** + * The fss embedded list write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_embedded_list_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_embedded_list_write_setting_t; + + #define fss_embedded_list_write_setting_t_initialize \ + { \ + fss_embedded_list_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_embedded_list_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_embedded_list_write_setting_delete_ + extern f_status_t fss_embedded_list_write_setting_delete(fss_embedded_list_write_setting_t * const setting); +#endif // _di_fss_embedded_list_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_embedded_list_write_setting_load_ + extern void fss_embedded_list_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting); +#endif // _di_fss_embedded_list_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_embedded_list_write_setting_unload_ + extern f_status_t fss_embedded_list_write_setting_unload(fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting); +#endif // _di_fss_embedded_list_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c index ddfb5f1..a5bd532 100644 --- a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c +++ b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.c @@ -6,62 +6,8 @@ extern "C" { #endif -#ifndef _di_fss_embedded_list_write_print_help_ - f_status_t fss_embedded_list_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_embedded_list_write_program_name_long_s, fss_embedded_list_write_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_embedded_list_write_short_file_s, fss_embedded_list_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_content_s, fss_embedded_list_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_double_s, fss_embedded_list_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_ignore_s, fss_embedded_list_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_object_s, fss_embedded_list_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_partial_s, fss_embedded_list_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_prepend_s, fss_embedded_list_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_single_s, fss_embedded_list_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - fll_program_print_help_option(file, context, fss_embedded_list_write_short_trim_s, fss_embedded_list_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); - - fll_program_print_help_usage(file, context, fss_embedded_list_write_program_name_s, f_string_empty_s); - - fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", file.stream, f_string_eol_s, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range (use this both before and after the range).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The FSS-0008 (Embedded List) specification does not support quoted names, therefore the parameters '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_single_s, context.set.notable); - fl_print_format(" and '%[%r%r%]' do nothing.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_double_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter '%[%r%r%]' designates to not escape any valid nested Object or Content within some Content.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_ignore_s, context.set.notable, f_string_eol_s); - fl_print_format(" This parameter requires two values.%r", file.stream, f_string_eol_s); - fl_print_format(" This parameter is not used for ignoring anything from the input pipe.%r", file.stream, f_string_eol_s); - fl_print_format(" This parameter must be specified after a '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s, context.set.notable); - fl_print_format(" parameter and this applies only to the Content represented by that specific '%[%r%r%]' parameter.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s, context.set.notable, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_embedded_list_write_print_help_ - #ifndef _di_fss_embedded_list_write_main_ - f_status_t fss_embedded_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_embedded_list_write_main(fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting) { f_status_t status = F_none; @@ -113,13 +59,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_embedded_list_write_parameter_help_e].result == f_console_result_found_e) { - fss_embedded_list_write_print_help(main->output.to, main->context); + fss_embedded_list_write_print_help(setting, main->message); return status; } if (main->parameters.array[fss_embedded_list_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_embedded_list_write_program_version_s); + fll_program_print_version(main->message, fss_embedded_list_write_program_version_s); return status; } @@ -412,7 +358,7 @@ extern "C" { if (!((++main->signal_check) % fss_embedded_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_embedded_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -431,7 +377,7 @@ extern "C" { if (!((++main->signal_check) % fss_embedded_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_embedded_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -454,7 +400,7 @@ extern "C" { if (!((++main->signal_check) % fss_embedded_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_embedded_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h index 23002ef..4347d39 100644 --- a/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h +++ b/level_3/fss_embedded_list_write/c/fss_embedded_list_write.h @@ -48,21 +48,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_embedded_list_write_print_help_ - extern f_status_t fss_embedded_list_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_embedded_list_write_print_help_ - -/** * Execute main program. * * Be sure to call fss_embedded_list_write_main_delete() after executing this. @@ -86,7 +71,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_embedded_list_write_main_ - extern f_status_t fss_embedded_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_embedded_list_write_main(fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting); #endif // _di_fss_embedded_list_write_main_ #ifdef __cplusplus diff --git a/level_3/fss_embedded_list_write/c/main.c b/level_3/fss_embedded_list_write/c/main.c index bd708bd..501e052 100644 --- a/level_3/fss_embedded_list_write/c/main.c +++ b/level_3/fss_embedded_list_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_extended_list_write_setting_t setting = fss_extended_list_write_setting_t_initialize; f_console_parameter_t parameters[] = fss_embedded_list_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_embedded_list_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_embedded_list_write_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_embedded_list_write_setting_load(arguments, &data, &setting); + } + + fss_embedded_list_write_main(&data, &setting); + + fss_embedded_list_write_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_embedded_list_write/c/print.c b/level_3/fss_embedded_list_write/c/print.c new file mode 100644 index 0000000..bddc7b7 --- /dev/null +++ b/level_3/fss_embedded_list_write/c/print.c @@ -0,0 +1,91 @@ +#include "fss_embedded_list_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_embedded_list_write_print_help_ + f_status_t fss_embedded_list_write_print_help(fss_embedded_list_write_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_embedded_list_write_program_name_long_s, fss_embedded_list_write_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_embedded_list_write_short_file_s, fss_embedded_list_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, fss_embedded_list_write_short_content_s, fss_embedded_list_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, fss_embedded_list_write_short_double_s, fss_embedded_list_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, fss_embedded_list_write_short_ignore_s, fss_embedded_list_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); + fll_program_print_help_option(print, fss_embedded_list_write_short_object_s, fss_embedded_list_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, fss_embedded_list_write_short_partial_s, fss_embedded_list_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); + fll_program_print_help_option(print, fss_embedded_list_write_short_prepend_s, fss_embedded_list_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); + fll_program_print_help_option(print, fss_embedded_list_write_short_single_s, fss_embedded_list_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + fll_program_print_help_option(print, fss_embedded_list_write_short_trim_s, fss_embedded_list_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); + + fll_program_print_help_usage(print, fss_embedded_list_write_program_name_s, f_string_empty_s); + + fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", print.to.stream, f_string_eol_s, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range (use this both before and after the range).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The FSS-0008 (Embedded List) specification does not support quoted names, therefore the parameters '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_single_s, print.set->notable); + fl_print_format(" and '%[%r%r%]' do nothing.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_double_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter '%[%r%r%]' designates to not escape any valid nested Object or Content within some Content.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_ignore_s, print.set->notable, f_string_eol_s); + fl_print_format(" This parameter requires two values.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This parameter is not used for ignoring anything from the input pipe.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This parameter must be specified after a '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s, print.set->notable); + fl_print_format(" parameter and this applies only to the Content represented by that specific '%[%r%r%]' parameter.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_embedded_list_write_long_content_s, print.set->notable, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_embedded_list_write_print_help_ + +#ifndef _di_fss_embedded_list_write_print_line_first_ + void fss_embedded_list_write_print_line_first(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_embedded_list_write_print_line_first_ + +#ifndef _di_fss_embedded_list_write_print_line_last_ + void fss_embedded_list_write_print_line_last(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_embedded_list_write_main_flag_verify_e) return; + if ((setting->flag & fss_embedded_list_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_embedded_list_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_embedded_list_write/c/print.h b/level_3/fss_embedded_list_write/c/print.h new file mode 100644 index 0000000..562dfed --- /dev/null +++ b/level_3/fss_embedded_list_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_embedded_list_write_print_h +#define _fss_embedded_list_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_embedded_list_write_print_help_ + extern f_status_t fss_embedded_list_write_print_help(fss_embedded_list_write_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_embedded_list_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_write_print_line_first_ + extern void fss_embedded_list_write_print_line_first(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_write_print_line_last_ + extern void fss_embedded_list_write_print_line_last(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_embedded_list_write_print_h diff --git a/level_3/fss_embedded_list_write/c/private-common.c b/level_3/fss_embedded_list_write/c/private-common.c index 656ffae..16c4cbb 100644 --- a/level_3/fss_embedded_list_write/c/private-common.c +++ b/level_3/fss_embedded_list_write/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_embedded_list_write_print_signal_received_ - void fss_embedded_list_write_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_embedded_list_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_write/c/private-common.h b/level_3/fss_embedded_list_write/c/private-common.h index 569d3ec..85df5d0 100644 --- a/level_3/fss_embedded_list_write/c/private-common.h +++ b/level_3/fss_embedded_list_write/c/private-common.h @@ -25,16 +25,6 @@ extern "C" { #define fss_embedded_list_write_common_allocation_small_d 128 #endif // _di_fss_embedded_list_write_common_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_embedded_list_write_print_signal_received_ - extern void fss_embedded_list_write_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_embedded_list_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_embedded_list_write/c/private-write.c b/level_3/fss_embedded_list_write/c/private-write.c index 2526241..3654add 100644 --- a/level_3/fss_embedded_list_write/c/private-write.c +++ b/level_3/fss_embedded_list_write/c/private-write.c @@ -172,7 +172,7 @@ extern "C" { if (!((++main->signal_check) % fss_embedded_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_embedded_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); f_string_dynamic_resize(0, &block); f_string_dynamic_resize(0, &object); @@ -388,7 +388,7 @@ extern "C" { if (!((++main->signal_check) % fss_embedded_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_embedded_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_embedded_list_write/data/build/settings b/level_3/fss_embedded_list_write/data/build/settings index ee5cdf4..2359e05 100644 --- a/level_3/fss_embedded_list_write/data/build/settings +++ b/level_3/fss_embedded_list_write/data/build/settings @@ -22,10 +22,10 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_embedded_list_write.c common.c private-common.c private-write.c +build_sources_library fss_embedded_list_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers fss_embedded_list_write.h common.h +build_sources_headers fss_embedded_list_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_extended_list_read/c/common.c b/level_3/fss_extended_list_read/c/common.c index e7fedce..1726e8f 100644 --- a/level_3/fss_extended_list_read/c/common.c +++ b/level_3/fss_extended_list_read/c/common.c @@ -67,6 +67,358 @@ extern "C" { } #endif // _di_fss_extended_list_read_main_delete_ +#ifndef _di_fss_extended_list_read_setting_delete_ + f_status_t fss_extended_list_read_setting_delete(fss_extended_list_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_extended_list_read_setting_delete_ + +#ifndef _di_fss_extended_list_read_setting_load_ + void fss_extended_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_extended_list_read_parameter_no_color_e, fss_extended_list_read_parameter_light_e, fss_extended_list_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_list_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_extended_list_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_extended_list_read_parameter_verbosity_quiet_e, fss_extended_list_read_parameter_verbosity_error_e, fss_extended_list_read_parameter_verbosity_verbose_e, fss_extended_list_read_parameter_verbosity_debug_e, fss_extended_list_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_list_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_extended_list_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_extended_list_read_parameter_from_bytesequence_e, fss_extended_list_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_list_read_parameter_from_bytesequence_e) { + if (setting->mode & fss_extended_list_read_mode_from_codepoint_e) { + setting->mode -= fss_extended_list_read_mode_from_codepoint_e; + } + + setting->mode |= fss_extended_list_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_list_read_parameter_from_codepoint_e) { + if (setting->mode & fss_extended_list_read_mode_from_bytesequence_e) { + setting->mode -= fss_extended_list_read_mode_from_bytesequence_e; + } + + setting->mode |= fss_extended_list_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_extended_list_read_parameter_to_bytesequence_e, fss_extended_list_read_parameter_to_codepoint_e, fss_extended_list_read_parameter_to_combining_e, fss_extended_list_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_list_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_list_read_parameter_to_bytesequence_e) { + if (setting->mode & fss_extended_list_read_mode_to_codepoint_e) { + setting->mode -= fss_extended_list_read_mode_to_codepoint_e; + } + + if (setting->mode & fss_extended_list_read_mode_to_combining_e) { + setting->mode -= fss_extended_list_read_mode_to_combining_e; + } + + if (setting->mode & fss_extended_list_read_mode_to_width_e) { + setting->mode -= fss_extended_list_read_mode_to_width_e; + } + + setting->mode |= fss_extended_list_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_list_read_parameter_to_codepoint_e) { + if (setting->mode & fss_extended_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_extended_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_list_read_mode_to_combining_e) { + setting->mode -= fss_extended_list_read_mode_to_combining_e; + } + + if (setting->mode & fss_extended_list_read_mode_to_width_e) { + setting->mode -= fss_extended_list_read_mode_to_width_e; + } + + setting->mode |= fss_extended_list_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_extended_list_read_parameter_to_combining_e) { + if (setting->mode & fss_extended_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_extended_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_list_read_mode_to_codepoint_e) { + setting->mode -= fss_extended_list_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_list_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_list_read_mode_to_width_e; + } + + setting->mode |= fss_extended_list_read_mode_to_combining_e; + } + else if (choices.array[choice] == fss_extended_list_read_parameter_to_width_e) { + if (setting->mode & fss_extended_list_read_mode_to_bytesequence_e) { + setting->mode -= fss_extended_list_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_list_read_mode_to_codepoint_e) { + setting->mode -= fss_extended_list_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_list_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_list_read_mode_to_combining_e; + } + + setting->mode |= fss_extended_list_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_extended_list_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_extended_list_read_parameter_to_file_e].values.used > 1) { + fss_extended_list_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_extended_list_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_extended_list_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_extended_list_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_extended_list_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_extended_list_read_main_flag_file_to_e; + } + else { + fss_extended_list_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_extended_list_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_extended_list_read_parameter_to_file_e].result == f_console_result_found_e) { + fss_extended_list_read_print_error_no_value(main, setting, fss_extended_list_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_extended_list_read_main_flag_file_to_e) { + setting->flag -= fss_extended_list_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_extended_list_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_extended_list_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_extended_list_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_extended_list_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_extended_list_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_extended_list_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_extended_list_read_main_flag_file_from_e; + } + else if (main->parameters.array[fss_extended_list_read_parameter_from_file_e].result == f_console_result_found_e) { + fss_extended_list_read_print_error_no_value(main, setting, fss_extended_list_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_extended_list_read_main_flag_file_from_e) { + setting->flag -= fss_extended_list_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_extended_list_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_extended_list_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_extended_list_read_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_extended_list_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_extended_list_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_extended_list_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_extended_list_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_read_main_flag_header_e; + } + + if (main->parameters.array[fss_extended_list_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_read_main_flag_separate_e; + } + + if (main->parameters.array[fss_extended_list_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_extended_list_read_setting_load_ + +#ifndef _di_fss_extended_list_read_setting_unload_ + f_status_t fss_extended_list_read_setting_unload(fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_extended_list_read_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_extended_list_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_read/c/common.h b/level_3/fss_extended_list_read/c/common.h index 59b7d8e..7360cbf 100644 --- a/level_3/fss_extended_list_read/c/common.h +++ b/level_3/fss_extended_list_read/c/common.h @@ -294,6 +294,66 @@ extern "C" { #endif // _di_fss_extended_list_read_delimit_modes_ /** + * Flags used to represent flags passed to the main function. + * + * fss_extended_list_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_extended_list_read_main_flag_e_ + enum { + fss_extended_list_read_main_flag_none_e = 0x0, + fss_extended_list_read_main_flag_file_from_e = 0x1, + fss_extended_list_read_main_flag_file_to_e = 0x2, + fss_extended_list_read_main_flag_header_e = 0x4, + fss_extended_list_read_main_flag_help_e = 0x8, + fss_extended_list_read_main_flag_separate_e = 0x10, + fss_extended_list_read_main_flag_strip_invalid_e = 0x20, + fss_extended_list_read_main_flag_verify_e = 0x40, + fss_extended_list_read_main_flag_version_e = 0x80, + }; +#endif // _di_fss_extended_list_read_main_flag_e_ + +/** + * The fss extended list read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_extended_list_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_extended_list_read_setting_t; + + #define fss_extended_list_read_setting_t_initialize \ + { \ + fss_extended_list_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_extended_list_read_setting_t_ + +/** * Deallocate main. * * @param main @@ -310,6 +370,72 @@ extern "C" { extern f_status_t fss_extended_list_read_main_delete(fll_program_data_t *main); #endif // _di_fss_extended_list_read_main_delete_ +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_extended_list_read_setting_delete_ + extern f_status_t fss_extended_list_read_setting_delete(fss_extended_list_read_setting_t * const setting); +#endif // _di_fss_extended_list_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_extended_list_read_setting_load_ + extern void fss_extended_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting); +#endif // _di_fss_extended_list_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_extended_list_read_setting_unload_ + extern f_status_t fss_extended_list_read_setting_unload(fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting); +#endif // _di_fss_extended_list_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_read/c/fss_extended_list_read.c b/level_3/fss_extended_list_read/c/fss_extended_list_read.c index 9981c39..218d78c 100644 --- a/level_3/fss_extended_list_read/c/fss_extended_list_read.c +++ b/level_3/fss_extended_list_read/c/fss_extended_list_read.c @@ -7,119 +7,8 @@ extern "C" { #endif -#ifndef _di_fss_extended_list_read_print_help_ - f_status_t fss_extended_list_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_extended_list_read_program_name_long_s, fss_extended_list_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_extended_list_read_short_at_s, fss_extended_list_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_content_s, fss_extended_list_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_columns_s, fss_extended_list_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_delimit_s, fss_extended_list_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_depth_s, fss_extended_list_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_empty_s, fss_extended_list_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_line_s, fss_extended_list_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_name_s, fss_extended_list_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_object_s, fss_extended_list_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_pipe_s, fss_extended_list_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_original_s, fss_extended_list_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_select_s, fss_extended_list_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_total_s, fss_extended_list_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(file, context, fss_extended_list_read_short_trim_s, fss_extended_list_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); - - fll_program_print_help_usage(file, context, fss_extended_list_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0003 Extended List standard.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", file.stream, f_string_eol_s); - fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, context.set.notable, f_string_eol_s); - - fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", file.stream, f_string_eol_s); - - fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_at_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", file.stream, f_string_eol_s); - fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_object_s, context.set.notable); - fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_total_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_at_s, context.set.notable); - fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_name_s, context.set.notable); - fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_at_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter value.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program may support parameters, such as %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, context.set.notable); - fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, context.set.notable, f_string_eol_s); - fl_print_format(" This is done to help ensure consistency for scripting.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, context.set.notable); - fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", file.stream, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, context.set.notable); - fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_trim_s, context.set.notable); - fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying both the %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_object_s, context.set.notable); - fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_content_s, context.set.notable, f_string_eol_s); - fl_print_format(" Both the Object and Content printed are already escaped.%r", file.stream, f_string_eol_s); - fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] accepts the following:%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_delimit_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Do not apply delimits.%r", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_none_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_all_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_object_s, context.set.notable, f_string_eol_s); - fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", file.stream, f_string_eol_s); - fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_greater_s, context.set.notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_lesser_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_delimit_s, context.set.notable, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_delimit_s, context.set.notable); - fl_print_format(" values %[%r%]", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_none_s, context.set.notable); - fl_print_format(" and %[%r%],", file.stream, context.set.notable, fss_extended_list_read_delimit_mode_name_all_s, context.set.notable); - fl_print_format(" overrule all other delimit values.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameters %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_columns_s, context.set.notable); - fl_print_format(" and %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, context.set.notable); - fl_print_format(" refer to a Content column.%r", file.stream, f_string_eol_s); - fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", file.stream, f_string_eol_s); - fl_print_format(" This is not to be confused with a depth.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_extended_list_read_print_help_ - #ifndef _di_fss_extended_list_read_main_ - f_status_t fss_extended_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_extended_list_read_main(fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting) { f_status_t status = F_none; @@ -169,13 +58,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_extended_list_read_parameter_help_e].result == f_console_result_found_e) { - fss_extended_list_read_print_help(main->output.to, main->context); + fss_extended_list_read_print_help(setting, main->message); return status; } if (main->parameters.array[fss_extended_list_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_extended_list_read_program_version_s); + fll_program_print_version(main->message, fss_extended_list_read_program_version_s); return status; } @@ -310,7 +199,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -515,7 +404,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -581,7 +470,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > fss_extended_list_read_block_max && fll_program_standard_signal_received(main)) { - fss_extended_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_extended_list_read/c/fss_extended_list_read.h b/level_3/fss_extended_list_read/c/fss_extended_list_read.h index 847c845..b2b6cc5 100644 --- a/level_3/fss_extended_list_read/c/fss_extended_list_read.h +++ b/level_3/fss_extended_list_read/c/fss_extended_list_read.h @@ -55,21 +55,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_extended_list_read_print_help_ - extern f_status_t fss_extended_list_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_extended_list_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -82,16 +67,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_extended_list_read_main_ - extern f_status_t fss_extended_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_extended_list_read_main(fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting); #endif // _di_fss_extended_list_read_main_ #ifdef __cplusplus diff --git a/level_3/fss_extended_list_read/c/main.c b/level_3/fss_extended_list_read/c/main.c index 30e46c9..aff8ca9 100644 --- a/level_3/fss_extended_list_read/c/main.c +++ b/level_3/fss_extended_list_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_extended_list_read_setting_t setting = fss_extended_list_read_setting_t_initialize; f_console_parameter_t parameters[] = fss_extended_list_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_extended_list_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_extended_list_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_extended_list_read_setting_load(arguments, &data, &setting); + } + + fss_extended_list_read_main(&data, &setting); + + fss_extended_list_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_extended_list_read/c/print.c b/level_3/fss_extended_list_read/c/print.c new file mode 100644 index 0000000..893c762 --- /dev/null +++ b/level_3/fss_extended_list_read/c/print.c @@ -0,0 +1,148 @@ +#include "fss_embedded_list_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_extended_list_read_print_help_ + f_status_t fss_extended_list_read_print_help(fss_extended_list_read_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_extended_list_read_program_name_long_s, fss_extended_list_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_extended_list_read_short_at_s, fss_extended_list_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(print, fss_extended_list_read_short_content_s, fss_extended_list_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); + fll_program_print_help_option(print, fss_extended_list_read_short_columns_s, fss_extended_list_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); + fll_program_print_help_option(print, fss_extended_list_read_short_delimit_s, fss_extended_list_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); + fll_program_print_help_option(print, fss_extended_list_read_short_depth_s, fss_extended_list_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(print, fss_extended_list_read_short_empty_s, fss_extended_list_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(print, fss_extended_list_read_short_line_s, fss_extended_list_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(print, fss_extended_list_read_short_name_s, fss_extended_list_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(print, fss_extended_list_read_short_object_s, fss_extended_list_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); + fll_program_print_help_option(print, fss_extended_list_read_short_pipe_s, fss_extended_list_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); + fll_program_print_help_option(print, fss_extended_list_read_short_original_s, fss_extended_list_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); + fll_program_print_help_option(print, fss_extended_list_read_short_select_s, fss_extended_list_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); + fll_program_print_help_option(print, fss_extended_list_read_short_total_s, fss_extended_list_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); + fll_program_print_help_option(print, fss_extended_list_read_short_trim_s, fss_extended_list_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); + + fll_program_print_help_usage(print, fss_extended_list_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0003 Extended List standard.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", print.to.stream, f_string_eol_s); + fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, print.set->notable, f_string_eol_s); + + fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", print.to.stream, f_string_eol_s); + + fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_at_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", print.to.stream, f_string_eol_s); + fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_object_s, print.set->notable); + fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_total_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_at_s, print.set->notable); + fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_name_s, print.set->notable); + fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_at_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter value.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program may support parameters, such as %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, print.set->notable); + fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, print.set->notable, f_string_eol_s); + fl_print_format(" This is done to help ensure consistency for scripting.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_depth_s, print.set->notable); + fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, print.set->notable); + fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_trim_s, print.set->notable); + fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying both the %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_object_s, print.set->notable); + fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_content_s, print.set->notable, f_string_eol_s); + fl_print_format(" Both the Object and Content printed are already escaped.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] accepts the following:%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_delimit_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Do not apply delimits.%r", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_none_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_all_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_object_s, print.set->notable, f_string_eol_s); + fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", print.to.stream, f_string_eol_s); + fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_greater_s, print.set->notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_lesser_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_delimit_s, print.set->notable, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_delimit_s, print.set->notable); + fl_print_format(" values %[%r%]", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_none_s, print.set->notable); + fl_print_format(" and %[%r%],", print.to.stream, print.set->notable, fss_extended_list_read_delimit_mode_name_all_s, print.set->notable); + fl_print_format(" overrule all other delimit values.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameters %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_columns_s, print.set->notable); + fl_print_format(" and %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_read_long_select_s, print.set->notable); + fl_print_format(" refer to a Content column.%r", print.to.stream, f_string_eol_s); + fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This is not to be confused with a depth.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_extended_list_read_print_help_ + +#ifndef _di_fss_embedded_list_read_print_line_first_ + void fss_embedded_list_read_print_line_first(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_embedded_list_read_print_line_first_ + +#ifndef _di_fss_embedded_list_read_print_line_last_ + void fss_embedded_list_read_print_line_last(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_embedded_list_read_main_flag_verify_e) return; + if ((setting->flag & fss_embedded_list_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_embedded_list_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_extended_list_read/c/print.h b/level_3/fss_extended_list_read/c/print.h new file mode 100644 index 0000000..73015d0 --- /dev/null +++ b/level_3/fss_extended_list_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_embedded_list_read_print_h +#define _fss_embedded_list_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_extended_list_read_print_help_ + extern f_status_t fss_extended_list_read_print_help(fss_extended_list_read_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_extended_list_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_read_print_line_first_ + extern void fss_embedded_list_read_print_line_first(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_read_print_line_last_ + extern void fss_embedded_list_read_print_line_last(fss_embedded_list_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_embedded_list_read_print_h diff --git a/level_3/fss_extended_list_read/c/private-common.c b/level_3/fss_extended_list_read/c/private-common.c index 688b59e..46fcfa1 100644 --- a/level_3/fss_extended_list_read/c/private-common.c +++ b/level_3/fss_extended_list_read/c/private-common.c @@ -56,24 +56,6 @@ extern "C" { } #endif // _di_fss_extended_list_read_depths_resize_ -#ifndef _di_fss_extended_list_read_print_signal_received_ - void fss_extended_list_read_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_extended_list_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_read/c/private-common.h b/level_3/fss_extended_list_read/c/private-common.h index 0dc07c4..8bd3c49 100644 --- a/level_3/fss_extended_list_read/c/private-common.h +++ b/level_3/fss_extended_list_read/c/private-common.h @@ -262,16 +262,6 @@ extern "C" { extern f_status_t fss_extended_list_read_depths_resize(const f_array_length_t length, fss_extended_list_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_extended_list_read_depths_resize_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_extended_list_read_print_signal_received_ - extern void fss_extended_list_read_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_extended_list_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_read/c/private-read.c b/level_3/fss_extended_list_read/c/private-read.c index 1da5a70..3494f4b 100644 --- a/level_3/fss_extended_list_read/c/private-read.c +++ b/level_3/fss_extended_list_read/c/private-read.c @@ -88,7 +88,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -176,7 +176,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_extended_list_read/data/build/settings b/level_3/fss_extended_list_read/data/build/settings index 683d0db..c67a02a 100644 --- a/level_3/fss_extended_list_read/data/build/settings +++ b/level_3/fss_extended_list_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_extended_list_read.c common.c private-common.c private-print.c private-read.c +build_sources_library fss_extended_list_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers fss_extended_list_read.h common.h +build_sources_headers fss_extended_list_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_extended_list_write/c/common.c b/level_3/fss_extended_list_write/c/common.c index 4adc3bb..ec3991a 100644 --- a/level_3/fss_extended_list_write/c/common.c +++ b/level_3/fss_extended_list_write/c/common.c @@ -49,6 +49,358 @@ extern "C" { } #endif // _di_fss_extended_list_write_main_delete_ +#ifndef _di_fss_extended_list_write_setting_delete_ + f_status_t fss_extended_list_write_setting_delete(fss_extended_list_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_extended_list_write_setting_delete_ + +#ifndef _di_fss_extended_list_write_setting_load_ + void fss_extended_list_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_extended_list_write_parameter_no_color_e, fss_extended_list_write_parameter_light_e, fss_extended_list_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_list_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_extended_list_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_extended_list_write_parameter_verbosity_quiet_e, fss_extended_list_write_parameter_verbosity_error_e, fss_extended_list_write_parameter_verbosity_verbose_e, fss_extended_list_write_parameter_verbosity_debug_e, fss_extended_list_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_list_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_extended_list_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_extended_list_write_parameter_from_bytesequence_e, fss_extended_list_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_list_write_parameter_from_bytesequence_e) { + if (setting->mode & fss_extended_list_write_mode_from_codepoint_e) { + setting->mode -= fss_extended_list_write_mode_from_codepoint_e; + } + + setting->mode |= fss_extended_list_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_list_write_parameter_from_codepoint_e) { + if (setting->mode & fss_extended_list_write_mode_from_bytesequence_e) { + setting->mode -= fss_extended_list_write_mode_from_bytesequence_e; + } + + setting->mode |= fss_extended_list_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_extended_list_write_parameter_to_bytesequence_e, fss_extended_list_write_parameter_to_codepoint_e, fss_extended_list_write_parameter_to_combining_e, fss_extended_list_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_list_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_list_write_parameter_to_bytesequence_e) { + if (setting->mode & fss_extended_list_write_mode_to_codepoint_e) { + setting->mode -= fss_extended_list_write_mode_to_codepoint_e; + } + + if (setting->mode & fss_extended_list_write_mode_to_combining_e) { + setting->mode -= fss_extended_list_write_mode_to_combining_e; + } + + if (setting->mode & fss_extended_list_write_mode_to_width_e) { + setting->mode -= fss_extended_list_write_mode_to_width_e; + } + + setting->mode |= fss_extended_list_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_list_write_parameter_to_codepoint_e) { + if (setting->mode & fss_extended_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_extended_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_list_write_mode_to_combining_e) { + setting->mode -= fss_extended_list_write_mode_to_combining_e; + } + + if (setting->mode & fss_extended_list_write_mode_to_width_e) { + setting->mode -= fss_extended_list_write_mode_to_width_e; + } + + setting->mode |= fss_extended_list_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_extended_list_write_parameter_to_combining_e) { + if (setting->mode & fss_extended_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_extended_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_list_write_mode_to_codepoint_e) { + setting->mode -= fss_extended_list_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_list_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_list_write_mode_to_width_e; + } + + setting->mode |= fss_extended_list_write_mode_to_combining_e; + } + else if (choices.array[choice] == fss_extended_list_write_parameter_to_width_e) { + if (setting->mode & fss_extended_list_write_mode_to_bytesequence_e) { + setting->mode -= fss_extended_list_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_list_write_mode_to_codepoint_e) { + setting->mode -= fss_extended_list_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_list_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_list_write_mode_to_combining_e; + } + + setting->mode |= fss_extended_list_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_extended_list_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_extended_list_write_parameter_to_file_e].values.used > 1) { + fss_extended_list_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_extended_list_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_extended_list_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_extended_list_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_extended_list_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_extended_list_write_main_flag_file_to_e; + } + else { + fss_extended_list_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_extended_list_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_extended_list_write_parameter_to_file_e].result == f_console_result_found_e) { + fss_extended_list_write_print_error_no_value(main, setting, fss_extended_list_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_extended_list_write_main_flag_file_to_e) { + setting->flag -= fss_extended_list_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_extended_list_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_extended_list_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_extended_list_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_extended_list_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_extended_list_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_extended_list_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_extended_list_write_main_flag_file_from_e; + } + else if (main->parameters.array[fss_extended_list_write_parameter_from_file_e].result == f_console_result_found_e) { + fss_extended_list_write_print_error_no_value(main, setting, fss_extended_list_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_extended_list_write_main_flag_file_from_e) { + setting->flag -= fss_extended_list_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_extended_list_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_extended_list_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_extended_list_write_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_extended_list_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_extended_list_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_extended_list_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_extended_list_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_write_main_flag_header_e; + } + + if (main->parameters.array[fss_extended_list_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_write_main_flag_separate_e; + } + + if (main->parameters.array[fss_extended_list_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_list_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_extended_list_write_setting_load_ + +#ifndef _di_fss_extended_list_write_setting_unload_ + f_status_t fss_extended_list_write_setting_unload(fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_extended_list_write_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_extended_list_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_write/c/common.h b/level_3/fss_extended_list_write/c/common.h index b80105e..2699c82 100644 --- a/level_3/fss_extended_list_write/c/common.h +++ b/level_3/fss_extended_list_write/c/common.h @@ -225,6 +225,132 @@ extern "C" { extern f_status_t fss_extended_list_write_main_delete(fll_program_data_t *main); #endif // _di_fss_extended_list_write_main_delete_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_extended_list_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_extended_list_write_main_flag_e_ + enum { + fss_extended_list_write_main_flag_none_e = 0x0, + fss_extended_list_write_main_flag_file_from_e = 0x1, + fss_extended_list_write_main_flag_file_to_e = 0x2, + fss_extended_list_write_main_flag_header_e = 0x4, + fss_extended_list_write_main_flag_help_e = 0x8, + fss_extended_list_write_main_flag_separate_e = 0x10, + fss_extended_list_write_main_flag_strip_invalid_e = 0x20, + fss_extended_list_write_main_flag_verify_e = 0x40, + fss_extended_list_write_main_flag_version_e = 0x80, + }; +#endif // _di_fss_extended_list_write_main_flag_e_ + +/** + * The fss extended list write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_extended_list_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_extended_list_write_setting_t; + + #define fss_extended_list_write_setting_t_initialize \ + { \ + fss_extended_list_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_extended_list_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_extended_list_write_setting_delete_ + extern f_status_t fss_extended_list_write_setting_delete(fss_extended_list_write_setting_t * const setting); +#endif // _di_fss_extended_list_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_extended_list_write_setting_load_ + extern void fss_extended_list_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting); +#endif // _di_fss_extended_list_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_extended_list_write_setting_unload_ + extern f_status_t fss_extended_list_write_setting_unload(fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting); +#endif // _di_fss_extended_list_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_write/c/fss_extended_list_write.c b/level_3/fss_extended_list_write/c/fss_extended_list_write.c index a82340b..4b3c9a6 100644 --- a/level_3/fss_extended_list_write/c/fss_extended_list_write.c +++ b/level_3/fss_extended_list_write/c/fss_extended_list_write.c @@ -6,62 +6,8 @@ extern "C" { #endif -#ifndef _di_fss_extended_list_write_print_help_ - f_status_t fss_extended_list_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_extended_list_write_program_name_long_s, fss_extended_list_write_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_extended_list_write_short_file_s, fss_extended_list_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_content_s, fss_extended_list_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_double_s, fss_extended_list_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_ignore_s, fss_extended_list_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_object_s, fss_extended_list_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_partial_s, fss_extended_list_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_prepend_s, fss_extended_list_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_single_s, fss_extended_list_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - fll_program_print_help_option(file, context, fss_extended_list_write_short_trim_s, fss_extended_list_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); - - fll_program_print_help_usage(file, context, fss_extended_list_write_program_name_s, f_string_empty_s); - - fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", file.stream, f_string_eol_s, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range (use this both before and after the range).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The FSS-0003 (Extended List) specification does not support quoted names, therefore the parameters '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_single_s, context.set.notable); - fl_print_format(" and '%[%r%r%]' do nothing.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_double_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter '%[%r%r%]' designates to not escape any valid nested Object or Content within some Content.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_ignore_s, context.set.notable, f_string_eol_s); - fl_print_format(" This parameter requires two values.%r", file.stream, f_string_eol_s); - fl_print_format(" This parameter is not used for ignoring anything from the input pipe.%r", file.stream, f_string_eol_s); - fl_print_format(" This parameter must be specified after a '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s, context.set.notable); - fl_print_format(" parameter and this applies only to the Content represented by that specific '%[%r%r%]' parameter.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s, context.set.notable, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_extended_list_write_print_help_ - #ifndef _di_fss_extended_list_write_main_ - f_status_t fss_extended_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_extended_list_write_main(fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting) { f_status_t status = F_none; @@ -113,13 +59,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_extended_list_write_parameter_help_e].result == f_console_result_found_e) { - fss_extended_list_write_print_help(main->output.to, main->context); + fss_extended_list_write_print_help(setting, main->message); return status; } if (main->parameters.array[fss_extended_list_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_extended_list_write_program_version_s); + fll_program_print_version(main->message, fss_extended_list_write_program_version_s); return status; } @@ -411,7 +357,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -430,7 +376,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -453,7 +399,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_extended_list_write/c/fss_extended_list_write.h b/level_3/fss_extended_list_write/c/fss_extended_list_write.h index ce18f5b..64f3df7 100644 --- a/level_3/fss_extended_list_write/c/fss_extended_list_write.h +++ b/level_3/fss_extended_list_write/c/fss_extended_list_write.h @@ -48,21 +48,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_extended_list_write_print_help_ - extern f_status_t fss_extended_list_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_extended_list_write_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -75,16 +60,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_extended_list_write_main_ - extern f_status_t fss_extended_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_extended_list_write_main(fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting); #endif // _di_fss_extended_list_write_main_ #ifdef __cplusplus diff --git a/level_3/fss_extended_list_write/c/main.c b/level_3/fss_extended_list_write/c/main.c index 6814f7d..40848be 100644 --- a/level_3/fss_extended_list_write/c/main.c +++ b/level_3/fss_extended_list_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_extended_list_write_setting_t setting = fss_extended_list_write_setting_t_initialize; f_console_parameter_t parameters[] = fss_extended_list_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_extended_list_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,21 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_extended_list_write_setting_load(arguments, &data, &setting); + } + const f_status_t status = fss_extended_list_write_main(&data, arguments); + fss_extended_list_write_main(&data, &setting); + + fss_extended_list_write_setting_unload(&data, &setting); + fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_extended_list_write/c/print.c b/level_3/fss_extended_list_write/c/print.c new file mode 100644 index 0000000..0b44a87 --- /dev/null +++ b/level_3/fss_extended_list_write/c/print.c @@ -0,0 +1,91 @@ +#include "fss_embedded_list_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_extended_list_write_print_help_ + f_status_t fss_extended_list_write_print_help(fss_extended_list_write_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_extended_list_write_program_name_long_s, fss_extended_list_write_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_extended_list_write_short_file_s, fss_extended_list_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, fss_extended_list_write_short_content_s, fss_extended_list_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, fss_extended_list_write_short_double_s, fss_extended_list_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, fss_extended_list_write_short_ignore_s, fss_extended_list_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); + fll_program_print_help_option(print, fss_extended_list_write_short_object_s, fss_extended_list_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, fss_extended_list_write_short_partial_s, fss_extended_list_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); + fll_program_print_help_option(print, fss_extended_list_write_short_prepend_s, fss_extended_list_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); + fll_program_print_help_option(print, fss_extended_list_write_short_single_s, fss_extended_list_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + fll_program_print_help_option(print, fss_extended_list_write_short_trim_s, fss_extended_list_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); + + fll_program_print_help_usage(print, fss_extended_list_write_program_name_s, f_string_empty_s); + + fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", print.to.stream, f_string_eol_s, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range (use this both before and after the range).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The FSS-0003 (Extended List) specification does not support quoted names, therefore the parameters '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_single_s, print.set->notable); + fl_print_format(" and '%[%r%r%]' do nothing.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_double_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter '%[%r%r%]' designates to not escape any valid nested Object or Content within some Content.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_ignore_s, print.set->notable, f_string_eol_s); + fl_print_format(" This parameter requires two values.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This parameter is not used for ignoring anything from the input pipe.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This parameter must be specified after a '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s, print.set->notable); + fl_print_format(" parameter and this applies only to the Content represented by that specific '%[%r%r%]' parameter.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_list_write_long_content_s, print.set->notable, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_extended_list_write_print_help_ + +#ifndef _di_fss_embedded_list_write_print_line_first_ + void fss_embedded_list_write_print_line_first(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_embedded_list_write_print_line_first_ + +#ifndef _di_fss_embedded_list_write_print_line_last_ + void fss_embedded_list_write_print_line_last(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_embedded_list_write_main_flag_verify_e) return; + if ((setting->flag & fss_embedded_list_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_embedded_list_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_extended_list_write/c/print.h b/level_3/fss_extended_list_write/c/print.h new file mode 100644 index 0000000..9da45b4 --- /dev/null +++ b/level_3/fss_extended_list_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_embedded_list_write_print_h +#define _fss_embedded_list_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_extended_list_write_print_help_ + extern f_status_t fss_extended_list_write_print_help(fss_extended_list_write_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_extended_list_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_write_print_line_first_ + extern void fss_embedded_list_write_print_line_first(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_embedded_list_write_print_line_last_ + extern void fss_embedded_list_write_print_line_last(fss_embedded_list_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_embedded_list_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_embedded_list_write_print_h diff --git a/level_3/fss_extended_list_write/c/private-common.c b/level_3/fss_extended_list_write/c/private-common.c index 24de260..4e3d529 100644 --- a/level_3/fss_extended_list_write/c/private-common.c +++ b/level_3/fss_extended_list_write/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_extended_list_write_print_signal_received_ - void fss_extended_list_write_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_extended_list_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_write/c/private-common.h b/level_3/fss_extended_list_write/c/private-common.h index 891a2ab..08cc099 100644 --- a/level_3/fss_extended_list_write/c/private-common.h +++ b/level_3/fss_extended_list_write/c/private-common.h @@ -24,16 +24,6 @@ extern "C" { #define fss_extended_list_write_common_allocation_small_d 128 #endif // _di_fss_extended_list_write_common_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_extended_list_write_print_signal_received_ - extern void fss_extended_list_write_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_extended_list_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_list_write/c/private-write.c b/level_3/fss_extended_list_write/c/private-write.c index 47e754f..1a44c8d 100644 --- a/level_3/fss_extended_list_write/c/private-write.c +++ b/level_3/fss_extended_list_write/c/private-write.c @@ -166,7 +166,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -379,7 +379,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_list_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_list_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_extended_list_write/data/build/settings b/level_3/fss_extended_list_write/data/build/settings index c8ca911..4d34c0e 100644 --- a/level_3/fss_extended_list_write/data/build/settings +++ b/level_3/fss_extended_list_write/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_extended_list_write.c common.c private-common.c private-write.c +build_sources_library fss_extended_list_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers fss_extended_list_write.h common.h +build_sources_headers fss_extended_list_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_extended_read/c/common.c b/level_3/fss_extended_read/c/common.c index 0f44d43..cb20d43 100644 --- a/level_3/fss_extended_read/c/common.c +++ b/level_3/fss_extended_read/c/common.c @@ -60,6 +60,358 @@ extern "C" { const f_string_static_t fss_extended_read_delimit_mode_name_lesser_s = macro_f_string_static_t_initialize(FSS_EXTENDED_READ_delimit_mode_name_lesser_s, 0, FSS_EXTENDED_READ_delimit_mode_name_lesser_s_length); #endif // _di_fss_extended_read_delimit_mode_ +#ifndef _di_fss_extended_read_setting_delete_ + f_status_t fss_extended_read_setting_delete(fss_extended_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_extended_read_setting_delete_ + +#ifndef _di_fss_extended_read_setting_load_ + void fss_extended_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_extended_read_parameter_no_color_e, fss_extended_read_parameter_light_e, fss_extended_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_extended_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_extended_read_parameter_verbosity_quiet_e, fss_extended_read_parameter_verbosity_error_e, fss_extended_read_parameter_verbosity_verbose_e, fss_extended_read_parameter_verbosity_debug_e, fss_extended_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_extended_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_extended_read_parameter_from_bytesequence_e, fss_extended_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_read_parameter_from_bytesequence_e) { + if (setting->mode & fss_extended_read_mode_from_codepoint_e) { + setting->mode -= fss_extended_read_mode_from_codepoint_e; + } + + setting->mode |= fss_extended_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_read_parameter_from_codepoint_e) { + if (setting->mode & fss_extended_read_mode_from_bytesequence_e) { + setting->mode -= fss_extended_read_mode_from_bytesequence_e; + } + + setting->mode |= fss_extended_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_extended_read_parameter_to_bytesequence_e, fss_extended_read_parameter_to_codepoint_e, fss_extended_read_parameter_to_combining_e, fss_extended_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_read_parameter_to_bytesequence_e) { + if (setting->mode & fss_extended_read_mode_to_codepoint_e) { + setting->mode -= fss_extended_read_mode_to_codepoint_e; + } + + if (setting->mode & fss_extended_read_mode_to_combining_e) { + setting->mode -= fss_extended_read_mode_to_combining_e; + } + + if (setting->mode & fss_extended_read_mode_to_width_e) { + setting->mode -= fss_extended_read_mode_to_width_e; + } + + setting->mode |= fss_extended_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_read_parameter_to_codepoint_e) { + if (setting->mode & fss_extended_read_mode_to_bytesequence_e) { + setting->mode -= fss_extended_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_read_mode_to_combining_e) { + setting->mode -= fss_extended_read_mode_to_combining_e; + } + + if (setting->mode & fss_extended_read_mode_to_width_e) { + setting->mode -= fss_extended_read_mode_to_width_e; + } + + setting->mode |= fss_extended_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_extended_read_parameter_to_combining_e) { + if (setting->mode & fss_extended_read_mode_to_bytesequence_e) { + setting->mode -= fss_extended_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_read_mode_to_codepoint_e) { + setting->mode -= fss_extended_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_read_mode_to_width_e; + } + + setting->mode |= fss_extended_read_mode_to_combining_e; + } + else if (choices.array[choice] == fss_extended_read_parameter_to_width_e) { + if (setting->mode & fss_extended_read_mode_to_bytesequence_e) { + setting->mode -= fss_extended_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_read_mode_to_codepoint_e) { + setting->mode -= fss_extended_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_read_mode_to_combining_e; + } + + setting->mode |= fss_extended_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_extended_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_extended_read_parameter_to_file_e].values.used > 1) { + fss_extended_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_extended_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_extended_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_extended_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_extended_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_extended_read_main_flag_file_to_e; + } + else { + fss_extended_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_extended_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_extended_read_parameter_to_file_e].result == f_console_result_found_e) { + fss_extended_read_print_error_no_value(main, setting, fss_extended_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_extended_read_main_flag_file_to_e) { + setting->flag -= fss_extended_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_extended_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_extended_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_extended_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_extended_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_extended_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_extended_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_extended_read_main_flag_file_from_e; + } + else if (main->parameters.array[fss_extended_read_parameter_from_file_e].result == f_console_result_found_e) { + fss_extended_read_print_error_no_value(main, setting, fss_extended_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_extended_read_main_flag_file_from_e) { + setting->flag -= fss_extended_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_extended_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_extended_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_extended_read_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_extended_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_extended_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_extended_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_extended_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_read_main_flag_header_e; + } + + if (main->parameters.array[fss_extended_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_read_main_flag_separate_e; + } + + if (main->parameters.array[fss_extended_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_extended_read_setting_load_ + +#ifndef _di_fss_extended_read_setting_unload_ + f_status_t fss_extended_read_setting_unload(fll_program_data_t * const main, fss_extended_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_extended_read_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_extended_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_read/c/common.h b/level_3/fss_extended_read/c/common.h index e4a38b6..76f3167 100644 --- a/level_3/fss_extended_read/c/common.h +++ b/level_3/fss_extended_read/c/common.h @@ -292,6 +292,132 @@ extern "C" { }; #endif // _di_fss_extended_read_delimit_modes_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_extended_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_extended_read_main_flag_e_ + enum { + fss_extended_read_main_flag_none_e = 0x0, + fss_extended_read_main_flag_file_from_e = 0x1, + fss_extended_read_main_flag_file_to_e = 0x2, + fss_extended_read_main_flag_header_e = 0x4, + fss_extended_read_main_flag_help_e = 0x8, + fss_extended_read_main_flag_separate_e = 0x10, + fss_extended_read_main_flag_strip_invalid_e = 0x20, + fss_extended_read_main_flag_verify_e = 0x40, + fss_extended_read_main_flag_version_e = 0x80, + }; +#endif // _di_fss_extended_read_main_flag_e_ + +/** + * The fss extended read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_extended_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_extended_read_setting_t; + + #define fss_extended_read_setting_t_initialize \ + { \ + fss_extended_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_extended_read_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_extended_read_setting_delete_ + extern f_status_t fss_extended_read_setting_delete(fss_extended_read_setting_t * const setting); +#endif // _di_fss_extended_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_extended_read_setting_load_ + extern void fss_extended_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_read_setting_t * const setting); +#endif // _di_fss_extended_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_extended_read_setting_unload_ + extern f_status_t fss_extended_read_setting_unload(fll_program_data_t * const main, fss_extended_read_setting_t * const setting); +#endif // _di_fss_extended_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_read/c/fss_extended_read.c b/level_3/fss_extended_read/c/fss_extended_read.c index 4226bb8..b64bbfa 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.c +++ b/level_3/fss_extended_read/c/fss_extended_read.c @@ -7,119 +7,8 @@ extern "C" { #endif -#ifndef _di_fss_extended_read_print_help_ - f_status_t fss_extended_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_extended_read_program_name_long_s, fss_extended_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_extended_read_short_at_s, fss_extended_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); - fll_program_print_help_option(file, context, fss_extended_read_short_content_s, fss_extended_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); - fll_program_print_help_option(file, context, fss_extended_read_short_columns_s, fss_extended_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); - fll_program_print_help_option(file, context, fss_extended_read_short_delimit_s, fss_extended_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(file, context, fss_extended_read_short_depth_s, fss_extended_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); - fll_program_print_help_option(file, context, fss_extended_read_short_empty_s, fss_extended_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); - fll_program_print_help_option(file, context, fss_extended_read_short_line_s, fss_extended_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); - fll_program_print_help_option(file, context, fss_extended_read_short_name_s, fss_extended_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); - fll_program_print_help_option(file, context, fss_extended_read_short_object_s, fss_extended_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); - fll_program_print_help_option(file, context, fss_extended_read_short_pipe_s, fss_extended_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(file, context, fss_extended_read_short_original_s, fss_extended_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); - fll_program_print_help_option(file, context, fss_extended_read_short_select_s, fss_extended_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); - fll_program_print_help_option(file, context, fss_extended_read_short_total_s, fss_extended_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(file, context, fss_extended_read_short_trim_s, fss_extended_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); - - fll_program_print_help_usage(file, context, fss_extended_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0001 Extended standard.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", file.stream, f_string_eol_s); - fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, context.set.notable, f_string_eol_s); - - fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", file.stream, f_string_eol_s); - - fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_at_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", file.stream, f_string_eol_s); - fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_object_s, context.set.notable); - fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_total_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_at_s, context.set.notable); - fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_name_s, context.set.notable); - fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_at_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter value.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program may support parameters, such as %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, context.set.notable); - fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, context.set.notable, f_string_eol_s); - fl_print_format(" This is done to help ensure consistency for scripting.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, context.set.notable); - fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", file.stream, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, context.set.notable); - fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_trim_s, context.set.notable); - fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying both the %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_object_s, context.set.notable); - fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_content_s, context.set.notable, f_string_eol_s); - fl_print_format(" Both the Object and Content printed are already escaped.%r", file.stream, f_string_eol_s); - fl_print_format(" Both the Object and Content are separated by a space.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] accepts the following:%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_delimit_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Do not apply delimits.%r", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_none_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_all_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_object_s, context.set.notable, f_string_eol_s); - fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", file.stream, f_string_eol_s); - fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_greater_s, context.set.notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_lesser_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_delimit_s, context.set.notable, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_delimit_s, context.set.notable); - fl_print_format(" values %[%r%]", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_none_s, context.set.notable); - fl_print_format(" and %[%r%],", file.stream, context.set.notable, fss_extended_read_delimit_mode_name_all_s, context.set.notable); - fl_print_format(" overrule all other delimit values.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameters %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_columns_s, context.set.notable); - fl_print_format(" and %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, context.set.notable); - fl_print_format(" refer to a Content column.%r", file.stream, f_string_eol_s); - fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", file.stream, f_string_eol_s); - fl_print_format(" This is not to be confused with a depth.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_extended_read_print_help_ - #ifndef _di_fss_extended_read_main_ - f_status_t fss_extended_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_extended_read_main(fll_program_data_t * const main, fss_extended_read_setting_t * const setting) { f_status_t status = F_none; @@ -169,13 +58,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_extended_read_parameter_help_e].result == f_console_result_found_e) { - fss_extended_read_print_help(main->output.to, main->context); + fss_extended_read_print_help(setting, main->message); return status; } if (main->parameters.array[fss_extended_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_extended_read_program_version_s); + fll_program_print_version(main->message, fss_extended_read_program_version_s); return status; } @@ -309,7 +198,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_signal); @@ -514,7 +403,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_signal); @@ -580,7 +469,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > fss_extended_read_block_max && fll_program_standard_signal_received(main)) { - fss_extended_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_extended_read/c/fss_extended_read.h b/level_3/fss_extended_read/c/fss_extended_read.h index bbdd1bf..9d28801 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.h +++ b/level_3/fss_extended_read/c/fss_extended_read.h @@ -55,21 +55,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_extended_read_print_help_ - extern f_status_t fss_extended_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_extended_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -91,7 +76,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_extended_read_main_ - extern f_status_t fss_extended_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_extended_read_main(fll_program_data_t * const main, fss_extended_read_setting_t * const setting); #endif // _di_fss_extended_read_main_ #ifdef __cplusplus diff --git a/level_3/fss_extended_read/c/main.c b/level_3/fss_extended_read/c/main.c index 95d7a45..5998ee6 100644 --- a/level_3/fss_extended_read/c/main.c +++ b/level_3/fss_extended_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_extended_read_setting_t setting = fss_extended_read_setting_t_initialize; f_console_parameter_t parameters[] = fss_extended_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_extended_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_extended_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_extended_read_setting_load(arguments, &data, &setting); + } + + fss_extended_read_main(&data, &setting); + + fss_extended_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_extended_read/c/print.c b/level_3/fss_extended_read/c/print.c new file mode 100644 index 0000000..c9f770a --- /dev/null +++ b/level_3/fss_extended_read/c/print.c @@ -0,0 +1,148 @@ +#include "fss_extended_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_extended_read_print_help_ + f_status_t fss_extended_read_print_help(fss_extended_read_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_extended_read_program_name_long_s, fss_extended_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_extended_read_short_at_s, fss_extended_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(print, fss_extended_read_short_content_s, fss_extended_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); + fll_program_print_help_option(print, fss_extended_read_short_columns_s, fss_extended_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); + fll_program_print_help_option(print, fss_extended_read_short_delimit_s, fss_extended_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); + fll_program_print_help_option(print, fss_extended_read_short_depth_s, fss_extended_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(print, fss_extended_read_short_empty_s, fss_extended_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(print, fss_extended_read_short_line_s, fss_extended_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(print, fss_extended_read_short_name_s, fss_extended_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(print, fss_extended_read_short_object_s, fss_extended_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); + fll_program_print_help_option(print, fss_extended_read_short_pipe_s, fss_extended_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); + fll_program_print_help_option(print, fss_extended_read_short_original_s, fss_extended_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); + fll_program_print_help_option(print, fss_extended_read_short_select_s, fss_extended_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); + fll_program_print_help_option(print, fss_extended_read_short_total_s, fss_extended_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); + fll_program_print_help_option(print, fss_extended_read_short_trim_s, fss_extended_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); + + fll_program_print_help_usage(print, fss_extended_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-0001 Extended standard.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", print.to.stream, f_string_eol_s); + fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, print.set->notable, f_string_eol_s); + + fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", print.to.stream, f_string_eol_s); + + fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_at_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", print.to.stream, f_string_eol_s); + fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_object_s, print.set->notable); + fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_total_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_at_s, print.set->notable); + fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_name_s, print.set->notable); + fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_at_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter value.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program may support parameters, such as %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, print.set->notable); + fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, print.set->notable, f_string_eol_s); + fl_print_format(" This is done to help ensure consistency for scripting.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_depth_s, print.set->notable); + fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, print.set->notable); + fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_trim_s, print.set->notable); + fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying both the %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_object_s, print.set->notable); + fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_content_s, print.set->notable, f_string_eol_s); + fl_print_format(" Both the Object and Content printed are already escaped.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Both the Object and Content are separated by a space.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] accepts the following:%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_delimit_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Do not apply delimits.%r", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_none_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_all_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_object_s, print.set->notable, f_string_eol_s); + fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", print.to.stream, f_string_eol_s); + fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_greater_s, print.set->notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_lesser_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_delimit_s, print.set->notable, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_delimit_s, print.set->notable); + fl_print_format(" values %[%r%]", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_none_s, print.set->notable); + fl_print_format(" and %[%r%],", print.to.stream, print.set->notable, fss_extended_read_delimit_mode_name_all_s, print.set->notable); + fl_print_format(" overrule all other delimit values.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameters %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_columns_s, print.set->notable); + fl_print_format(" and %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_read_long_select_s, print.set->notable); + fl_print_format(" refer to a Content column.%r", print.to.stream, f_string_eol_s); + fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This is not to be confused with a depth.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_extended_read_print_help_ + +#ifndef _di_fss_extended_read_print_line_first_ + void fss_extended_read_print_line_first(fss_extended_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_extended_read_print_line_first_ + +#ifndef _di_fss_extended_read_print_line_last_ + void fss_extended_read_print_line_last(fss_extended_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_extended_read_main_flag_verify_e) return; + if ((setting->flag & fss_extended_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_extended_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_extended_read/c/print.h b/level_3/fss_extended_read/c/print.h new file mode 100644 index 0000000..7d543dc --- /dev/null +++ b/level_3/fss_extended_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_extended_read_print_h +#define _fss_extended_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_extended_read_print_help_ + extern f_status_t fss_extended_read_print_help(fss_extended_read_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_extended_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_extended_read_print_line_first_ + extern void fss_extended_read_print_line_first(fss_extended_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_extended_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_extended_read_print_line_last_ + extern void fss_extended_read_print_line_last(fss_extended_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_extended_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_extended_read_print_h diff --git a/level_3/fss_extended_read/c/private-common.c b/level_3/fss_extended_read/c/private-common.c index 9c7dcb1..ac6911f 100644 --- a/level_3/fss_extended_read/c/private-common.c +++ b/level_3/fss_extended_read/c/private-common.c @@ -57,24 +57,6 @@ extern "C" { } #endif // _di_fss_extended_read_depths_resize_ -#ifndef _di_fss_extended_read_print_signal_received_ - void fss_extended_read_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_extended_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_read/c/private-common.h b/level_3/fss_extended_read/c/private-common.h index cbbe685..a25d201 100644 --- a/level_3/fss_extended_read/c/private-common.h +++ b/level_3/fss_extended_read/c/private-common.h @@ -261,16 +261,6 @@ extern "C" { extern f_status_t fss_extended_read_depths_resize(const f_array_length_t length, fss_extended_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_extended_read_depths_resize_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_extended_read_print_signal_received_ - extern void fss_extended_read_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_extended_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_read/c/private-read.c b/level_3/fss_extended_read/c/private-read.c index d4f7950..fedaa0e 100644 --- a/level_3/fss_extended_read/c/private-read.c +++ b/level_3/fss_extended_read/c/private-read.c @@ -92,7 +92,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -180,7 +180,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_extended_read/data/build/settings b/level_3/fss_extended_read/data/build/settings index 7b6720a..42d9f1c 100644 --- a/level_3/fss_extended_read/data/build/settings +++ b/level_3/fss_extended_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_extended_read.c common.c private-common.c private-print.c private-read.c +build_sources_library fss_extended_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers fss_extended_read.h common.h +build_sources_headers fss_extended_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_extended_write/c/common.c b/level_3/fss_extended_write/c/common.c index 12ecb72..f432360 100644 --- a/level_3/fss_extended_write/c/common.c +++ b/level_3/fss_extended_write/c/common.c @@ -42,6 +42,358 @@ extern "C" { const f_string_static_t fss_extended_write_long_trim_s = macro_f_string_static_t_initialize(FSS_EXTENDED_WRITE_long_trim_s, 0, FSS_EXTENDED_WRITE_long_trim_s_length); #endif // _di_fss_extended_write_parameters_ +#ifndef _di_fss_extended_write_setting_delete_ + f_status_t fss_extended_write_setting_delete(fss_extended_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_extended_write_setting_delete_ + +#ifndef _di_fss_extended_write_setting_load_ + void fss_extended_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_extended_write_parameter_no_color_e, fss_extended_write_parameter_light_e, fss_extended_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_extended_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_extended_write_parameter_verbosity_quiet_e, fss_extended_write_parameter_verbosity_error_e, fss_extended_write_parameter_verbosity_verbose_e, fss_extended_write_parameter_verbosity_debug_e, fss_extended_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_extended_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_extended_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_extended_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_extended_write_parameter_from_bytesequence_e, fss_extended_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_write_parameter_from_bytesequence_e) { + if (setting->mode & fss_extended_write_mode_from_codepoint_e) { + setting->mode -= fss_extended_write_mode_from_codepoint_e; + } + + setting->mode |= fss_extended_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_write_parameter_from_codepoint_e) { + if (setting->mode & fss_extended_write_mode_from_bytesequence_e) { + setting->mode -= fss_extended_write_mode_from_bytesequence_e; + } + + setting->mode |= fss_extended_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_extended_write_parameter_to_bytesequence_e, fss_extended_write_parameter_to_codepoint_e, fss_extended_write_parameter_to_combining_e, fss_extended_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_extended_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_extended_write_parameter_to_bytesequence_e) { + if (setting->mode & fss_extended_write_mode_to_codepoint_e) { + setting->mode -= fss_extended_write_mode_to_codepoint_e; + } + + if (setting->mode & fss_extended_write_mode_to_combining_e) { + setting->mode -= fss_extended_write_mode_to_combining_e; + } + + if (setting->mode & fss_extended_write_mode_to_width_e) { + setting->mode -= fss_extended_write_mode_to_width_e; + } + + setting->mode |= fss_extended_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_extended_write_parameter_to_codepoint_e) { + if (setting->mode & fss_extended_write_mode_to_bytesequence_e) { + setting->mode -= fss_extended_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_write_mode_to_combining_e) { + setting->mode -= fss_extended_write_mode_to_combining_e; + } + + if (setting->mode & fss_extended_write_mode_to_width_e) { + setting->mode -= fss_extended_write_mode_to_width_e; + } + + setting->mode |= fss_extended_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_extended_write_parameter_to_combining_e) { + if (setting->mode & fss_extended_write_mode_to_bytesequence_e) { + setting->mode -= fss_extended_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_write_mode_to_codepoint_e) { + setting->mode -= fss_extended_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_write_mode_to_width_e; + } + + setting->mode |= fss_extended_write_mode_to_combining_e; + } + else if (choices.array[choice] == fss_extended_write_parameter_to_width_e) { + if (setting->mode & fss_extended_write_mode_to_bytesequence_e) { + setting->mode -= fss_extended_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_extended_write_mode_to_codepoint_e) { + setting->mode -= fss_extended_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_extended_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_extended_write_mode_to_combining_e; + } + + setting->mode |= fss_extended_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_extended_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_extended_write_parameter_to_file_e].values.used > 1) { + fss_extended_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_extended_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_extended_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_extended_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_extended_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_extended_write_main_flag_file_to_e; + } + else { + fss_extended_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_extended_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_extended_write_parameter_to_file_e].result == f_console_result_found_e) { + fss_extended_write_print_error_no_value(main, setting, fss_extended_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_extended_write_main_flag_file_to_e) { + setting->flag -= fss_extended_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_extended_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_extended_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_extended_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_extended_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_extended_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_extended_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_extended_write_main_flag_file_from_e; + } + else if (main->parameters.array[fss_extended_write_parameter_from_file_e].result == f_console_result_found_e) { + fss_extended_write_print_error_no_value(main, setting, fss_extended_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_extended_write_main_flag_file_from_e) { + setting->flag -= fss_extended_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_extended_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_extended_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_extended_write_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_extended_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_extended_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_extended_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_extended_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_write_main_flag_header_e; + } + + if (main->parameters.array[fss_extended_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_write_main_flag_separate_e; + } + + if (main->parameters.array[fss_extended_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_extended_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_extended_write_setting_load_ + +#ifndef _di_fss_extended_write_setting_unload_ + f_status_t fss_extended_write_setting_unload(fll_program_data_t * const main, fss_extended_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_extended_write_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_extended_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_write/c/common.h b/level_3/fss_extended_write/c/common.h index 3ba6427..03ba6d0 100644 --- a/level_3/fss_extended_write/c/common.h +++ b/level_3/fss_extended_write/c/common.h @@ -208,6 +208,132 @@ extern "C" { #define fss_extended_write_total_parameters_d 20 #endif // _di_fss_extended_write_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_extended_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_extended_write_main_flag_e_ + enum { + fss_extended_write_main_flag_none_e = 0x0, + fss_extended_write_main_flag_file_from_e = 0x1, + fss_extended_write_main_flag_file_to_e = 0x2, + fss_extended_write_main_flag_header_e = 0x4, + fss_extended_write_main_flag_help_e = 0x8, + fss_extended_write_main_flag_separate_e = 0x10, + fss_extended_write_main_flag_strip_invalid_e = 0x20, + fss_extended_write_main_flag_verify_e = 0x40, + fss_extended_write_main_flag_version_e = 0x80, + }; +#endif // _di_fss_extended_write_main_flag_e_ + +/** + * The fss extended write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_extended_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_extended_write_setting_t; + + #define fss_extended_write_setting_t_initialize \ + { \ + fss_extended_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_extended_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_extended_write_setting_delete_ + extern f_status_t fss_extended_write_setting_delete(fss_extended_write_setting_t * const setting); +#endif // _di_fss_extended_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_extended_write_setting_load_ + extern void fss_extended_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_write_setting_t * const setting); +#endif // _di_fss_extended_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_extended_write_setting_unload_ + extern f_status_t fss_extended_write_setting_unload(fll_program_data_t * const main, fss_extended_write_setting_t * const setting); +#endif // _di_fss_extended_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_write/c/fss_extended_write.c b/level_3/fss_extended_write/c/fss_extended_write.c index 9ecf12e..de6d4b9 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.c +++ b/level_3/fss_extended_write/c/fss_extended_write.c @@ -6,59 +6,8 @@ extern "C" { #endif -#ifndef _di_fss_extended_write_print_help_ - f_status_t fss_extended_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_extended_write_program_name_long_s, fss_extended_write_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_extended_write_short_file_s, fss_extended_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, fss_extended_write_short_content_s, fss_extended_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, fss_extended_write_short_double_s, fss_extended_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, fss_extended_write_short_ignore_s, fss_extended_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); - fll_program_print_help_option(file, context, fss_extended_write_short_object_s, fss_extended_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, fss_extended_write_short_partial_s, fss_extended_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); - fll_program_print_help_option(file, context, fss_extended_write_short_prepend_s, fss_extended_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); - fll_program_print_help_option(file, context, fss_extended_write_short_single_s, fss_extended_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - fll_program_print_help_option(file, context, fss_extended_write_short_trim_s, fss_extended_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); - - fll_program_print_help_usage(file, context, fss_extended_write_program_name_s, f_string_empty_s); - - fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", file.stream, f_string_eol_s, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The FSS-0001 (Extended) specification does not support multi-line Content, therefore the parameter '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_write_long_prepend_s, context.set.notable); - fl_print_format(" does nothing.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_extended_write_long_ignore_s, context.set.notable, f_string_eol_s); - fl_print_format(" This parameter requires two values.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_extended_write_print_help_ - #ifndef _di_fss_extended_write_main_ - f_status_t fss_extended_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_extended_write_main(fll_program_data_t * const main, fss_extended_write_setting_t * const setting) { f_status_t status = F_none; @@ -110,13 +59,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_extended_write_parameter_help_e].result == f_console_result_found_e) { - fss_extended_write_print_help(main->output.to, main->context); + fss_extended_write_print_help(setting, main->message); return status; } if (main->parameters.array[fss_extended_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_extended_write_program_version_s); + fll_program_print_version(main->message, fss_extended_write_program_version_s); return status; } @@ -423,7 +372,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -470,7 +419,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_extended_write/c/fss_extended_write.h b/level_3/fss_extended_write/c/fss_extended_write.h index b444dfd..e1da061 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.h +++ b/level_3/fss_extended_write/c/fss_extended_write.h @@ -48,21 +48,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_extended_write_print_help_ - extern f_status_t fss_extended_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_extended_write_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -75,16 +60,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_extended_write_main_ - extern f_status_t fss_extended_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_extended_write_main(fll_program_data_t * const main, fss_extended_write_setting_t * const setting); #endif // _di_fss_extended_write_main_ #ifdef __cplusplus diff --git a/level_3/fss_extended_write/c/main.c b/level_3/fss_extended_write/c/main.c index 48d1286..c6cc6f3 100644 --- a/level_3/fss_extended_write/c/main.c +++ b/level_3/fss_extended_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_extended_write_setting_t setting = fss_extended_write_setting_t_initialize; f_console_parameter_t parameters[] = fss_extended_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_extended_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_extended_write_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_extended_write_setting_load(arguments, &data, &setting); + } + + fss_extended_write_main(&data, &setting); + + fss_extended_write_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_extended_write/c/print.c b/level_3/fss_extended_write/c/print.c new file mode 100644 index 0000000..9e5e72f --- /dev/null +++ b/level_3/fss_extended_write/c/print.c @@ -0,0 +1,88 @@ +#include "fss_extended_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_extended_write_print_help_ + f_status_t fss_extended_write_print_help(fss_extended_write_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_extended_write_program_name_long_s, fss_extended_write_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_extended_write_short_file_s, fss_extended_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, fss_extended_write_short_content_s, fss_extended_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, fss_extended_write_short_double_s, fss_extended_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, fss_extended_write_short_ignore_s, fss_extended_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); + fll_program_print_help_option(print, fss_extended_write_short_object_s, fss_extended_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, fss_extended_write_short_partial_s, fss_extended_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); + fll_program_print_help_option(print, fss_extended_write_short_prepend_s, fss_extended_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); + fll_program_print_help_option(print, fss_extended_write_short_single_s, fss_extended_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + fll_program_print_help_option(print, fss_extended_write_short_trim_s, fss_extended_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); + + fll_program_print_help_usage(print, fss_extended_write_program_name_s, f_string_empty_s); + + fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", print.to.stream, f_string_eol_s, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The FSS-0001 (Extended) specification does not support multi-line Content, therefore the parameter '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_write_long_prepend_s, print.set->notable); + fl_print_format(" does nothing.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_extended_write_long_ignore_s, print.set->notable, f_string_eol_s); + fl_print_format(" This parameter requires two values.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_extended_write_print_help_ + +#ifndef _di_fss_extended_write_print_line_first_ + void fss_extended_write_print_line_first(fss_extended_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_extended_write_print_line_first_ + +#ifndef _di_fss_extended_write_print_line_last_ + void fss_extended_write_print_line_last(fss_extended_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_extended_write_main_flag_verify_e) return; + if ((setting->flag & fss_extended_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_extended_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_extended_write/c/print.h b/level_3/fss_extended_write/c/print.h new file mode 100644 index 0000000..79dffc5 --- /dev/null +++ b/level_3/fss_extended_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_extended_write_print_h +#define _fss_extended_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_extended_write_print_help_ + extern f_status_t fss_extended_write_print_help(fss_extended_write_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_extended_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_extended_write_print_line_first_ + extern void fss_extended_write_print_line_first(fss_extended_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_extended_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_extended_write_print_line_last_ + extern void fss_extended_write_print_line_last(fss_extended_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_extended_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_extended_write_print_h diff --git a/level_3/fss_extended_write/c/private-common.c b/level_3/fss_extended_write/c/private-common.c index 2d5b189..635db9c 100644 --- a/level_3/fss_extended_write/c/private-common.c +++ b/level_3/fss_extended_write/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_extended_write_print_signal_received_ - void fss_extended_write_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_extended_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_write/c/private-common.h b/level_3/fss_extended_write/c/private-common.h index a1f8179..d7617be 100644 --- a/level_3/fss_extended_write/c/private-common.h +++ b/level_3/fss_extended_write/c/private-common.h @@ -24,16 +24,6 @@ extern "C" { #define fss_extended_write_common_allocation_small_d 128 #endif // _di_fss_extended_write_common_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_extended_write_print_signal_received_ - extern void fss_extended_write_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_extended_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_extended_write/c/private-write.c b/level_3/fss_extended_write/c/private-write.c index a33d943..c1cdbe4 100644 --- a/level_3/fss_extended_write/c/private-write.c +++ b/level_3/fss_extended_write/c/private-write.c @@ -180,7 +180,7 @@ extern "C" { if (!((++main->signal_check) % fss_extended_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_extended_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_extended_write/data/build/settings b/level_3/fss_extended_write/data/build/settings index 151ed40..22315b9 100644 --- a/level_3/fss_extended_write/data/build/settings +++ b/level_3/fss_extended_write/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_extended_write.c common.c private-common.c private-write.c +build_sources_library fss_extended_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers fss_extended_write.h common.h +build_sources_headers fss_extended_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_identify/c/common.c b/level_3/fss_identify/c/common.c index 2ab2fa7..2e87b18 100644 --- a/level_3/fss_identify/c/common.c +++ b/level_3/fss_identify/c/common.c @@ -27,6 +27,358 @@ extern "C" { const f_string_static_t fss_identify_long_total_s = macro_f_string_static_t_initialize(FSS_IDENTIFY_long_total_s, 0, FSS_IDENTIFY_long_total_s_length); #endif // _di_fss_identify_parameters_ +#ifndef _di_fss_identify_setting_delete_ + f_status_t fss_identify_setting_delete(fss_identify_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_identify_setting_delete_ + +#ifndef _di_fss_identify_setting_load_ + void fss_identify_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_identify_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_identify_parameter_no_color_e, fss_identify_parameter_light_e, fss_identify_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_identify_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_identify_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_identify_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_identify_parameter_verbosity_quiet_e, fss_identify_parameter_verbosity_error_e, fss_identify_parameter_verbosity_verbose_e, fss_identify_parameter_verbosity_debug_e, fss_identify_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_identify_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_identify_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_identify_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_identify_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_identify_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_identify_parameter_from_bytesequence_e, fss_identify_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_identify_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_identify_parameter_from_bytesequence_e) { + if (setting->mode & fss_identify_mode_from_codepoint_e) { + setting->mode -= fss_identify_mode_from_codepoint_e; + } + + setting->mode |= fss_identify_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_identify_parameter_from_codepoint_e) { + if (setting->mode & fss_identify_mode_from_bytesequence_e) { + setting->mode -= fss_identify_mode_from_bytesequence_e; + } + + setting->mode |= fss_identify_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_identify_parameter_to_bytesequence_e, fss_identify_parameter_to_codepoint_e, fss_identify_parameter_to_combining_e, fss_identify_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_identify_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_identify_parameter_to_bytesequence_e) { + if (setting->mode & fss_identify_mode_to_codepoint_e) { + setting->mode -= fss_identify_mode_to_codepoint_e; + } + + if (setting->mode & fss_identify_mode_to_combining_e) { + setting->mode -= fss_identify_mode_to_combining_e; + } + + if (setting->mode & fss_identify_mode_to_width_e) { + setting->mode -= fss_identify_mode_to_width_e; + } + + setting->mode |= fss_identify_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_identify_parameter_to_codepoint_e) { + if (setting->mode & fss_identify_mode_to_bytesequence_e) { + setting->mode -= fss_identify_mode_to_bytesequence_e; + } + + if (setting->mode & fss_identify_mode_to_combining_e) { + setting->mode -= fss_identify_mode_to_combining_e; + } + + if (setting->mode & fss_identify_mode_to_width_e) { + setting->mode -= fss_identify_mode_to_width_e; + } + + setting->mode |= fss_identify_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_identify_parameter_to_combining_e) { + if (setting->mode & fss_identify_mode_to_bytesequence_e) { + setting->mode -= fss_identify_mode_to_bytesequence_e; + } + + if (setting->mode & fss_identify_mode_to_codepoint_e) { + setting->mode -= fss_identify_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_identify_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_identify_mode_to_width_e; + } + + setting->mode |= fss_identify_mode_to_combining_e; + } + else if (choices.array[choice] == fss_identify_parameter_to_width_e) { + if (setting->mode & fss_identify_mode_to_bytesequence_e) { + setting->mode -= fss_identify_mode_to_bytesequence_e; + } + + if (setting->mode & fss_identify_mode_to_codepoint_e) { + setting->mode -= fss_identify_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_identify_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_identify_mode_to_combining_e; + } + + setting->mode |= fss_identify_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_identify_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_identify_parameter_to_file_e].values.used > 1) { + fss_identify_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_identify_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_identify_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_identify_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_identify_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_identify_main_flag_file_to_e; + } + else { + fss_identify_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_identify_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_identify_parameter_to_file_e].result == f_console_result_found_e) { + fss_identify_print_error_no_value(main, setting, fss_identify_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_identify_main_flag_file_to_e) { + setting->flag -= fss_identify_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_identify_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_identify_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_identify_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_identify_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_identify_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_identify_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_identify_main_flag_file_from_e; + } + else if (main->parameters.array[fss_identify_parameter_from_file_e].result == f_console_result_found_e) { + fss_identify_print_error_no_value(main, setting, fss_identify_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_identify_main_flag_file_from_e) { + setting->flag -= fss_identify_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_identify_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_identify_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_identify_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_identify_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_identify_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_identify_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_identify_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_identify_main_flag_header_e; + } + + if (main->parameters.array[fss_identify_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_identify_main_flag_separate_e; + } + + if (main->parameters.array[fss_identify_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_identify_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_identify_setting_load_ + +#ifndef _di_fss_identify_setting_unload_ + f_status_t fss_identify_setting_unload(fll_program_data_t * const main, fss_identify_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_identify_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_identify_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/common.h b/level_3/fss_identify/c/common.h index 38764dd..8fa4c91 100644 --- a/level_3/fss_identify/c/common.h +++ b/level_3/fss_identify/c/common.h @@ -152,6 +152,132 @@ extern "C" { #define fss_identify_total_parameters_d 17 #endif // _di_fss_identify_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_identify_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_identify_main_flag_e_ + enum { + fss_identify_main_flag_none_e = 0x0, + fss_identify_main_flag_file_from_e = 0x1, + fss_identify_main_flag_file_to_e = 0x2, + fss_identify_main_flag_header_e = 0x4, + fss_identify_main_flag_help_e = 0x8, + fss_identify_main_flag_separate_e = 0x10, + fss_identify_main_flag_strip_invalid_e = 0x20, + fss_identify_main_flag_verify_e = 0x40, + fss_identify_main_flag_version_e = 0x80, + }; +#endif // _di_fss_identify_main_flag_e_ + +/** + * The fss identify main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_identify_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_identify_setting_t; + + #define fss_identify_setting_t_initialize \ + { \ + fss_identify_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_identify_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_identify_setting_delete_ + extern f_status_t fss_identify_setting_delete(fss_identify_setting_t * const setting); +#endif // _di_fss_identify_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_identify_setting_load_ + extern void fss_identify_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_identify_setting_t * const setting); +#endif // _di_fss_identify_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_identify_setting_unload_ + extern f_status_t fss_identify_setting_unload(fll_program_data_t * const main, fss_identify_setting_t * const setting); +#endif // _di_fss_identify_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/fss_identify.c b/level_3/fss_identify/c/fss_identify.c index f42a1ff..f5a0711 100644 --- a/level_3/fss_identify/c/fss_identify.c +++ b/level_3/fss_identify/c/fss_identify.c @@ -6,60 +6,8 @@ extern "C" { #endif -#ifndef _di_fss_identify_print_help_ - f_status_t fss_identify_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_identify_program_name_long_s, fss_identify_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_identify_short_content_s, fss_identify_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the Identifier content (the 4-digit hexidecimal type code)."); - fll_program_print_help_option(file, context, fss_identify_short_object_s, fss_identify_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Identifier object (the name)."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_identify_short_line_s, fss_identify_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Identifier at the given line."); - fll_program_print_help_option(file, context, fss_identify_short_name_s, fss_identify_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select FSS using this full or partial type name or code."); - fll_program_print_help_option(file, context, fss_identify_short_total_s, fss_identify_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the total Identifiers found."); - - fll_program_print_help_usage(file, context, fss_identify_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r The %[%r%r%] parameter refers to the file lines and not the lines in a given file.%r%r", file.stream, f_string_eol_s, context.set.notable, f_console_symbol_long_enable_s, fss_identify_long_line_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" If neither the %[%r%r%] nor", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_identify_long_object_s, context.set.notable); - fl_print_format(" %[%r%r%] are specified, then the default behavior is to print both.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_identify_long_content_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying the %[%r%r%] parameter, neither the", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_identify_long_total_s, context.set.notable); - fl_print_format(" %[%r%r%] nor the", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_identify_long_object_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter may be specified.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_identify_long_content_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" An FSS file is identified by the following format: '%[# Object-Content%]'", file.stream, context.set.notable, context.set.notable); - fl_print_format(" where the Object, is a machine-name representing the name and may only consist of \"word\" characters and the Content is a 4-digit hexidecimal number representing a particular variant of the Object.%r", file.stream, f_string_eol_s); - fl_print_format(" This identifier, if provided, must exist on the first line in a file and must begin with the pound character: '#'.%r", file.stream, f_string_eol_s); - fl_print_format(" Whitespace must follow this pound character.%r", file.stream, f_string_eol_s); - fl_print_format(" There may be multiple Object and Content pairs, separated by white space, such as: \"# fss-0002 fss-0000 iki-0002\".%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_identify_print_help_ - #ifndef _di_fss_identify_main_ - f_status_t fss_identify_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_identify_main(fll_program_data_t * const main, fss_identify_setting_t * const setting) { f_status_t status = F_none; @@ -109,13 +57,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_identify_parameter_help_e].result == f_console_result_found_e) { - fss_identify_print_help(main->output.to, main->context); + fss_identify_print_help(setting, main->message); return F_none; } if (main->parameters.array[fss_identify_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_identify_program_version_s); + fll_program_print_version(main->message, fss_identify_program_version_s); return F_none; } @@ -254,7 +202,7 @@ extern "C" { if (!((++main->signal_check) % fss_identify_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_identify_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_identify/c/fss_identify.h b/level_3/fss_identify/c/fss_identify.h index 501d157..a7750e6 100644 --- a/level_3/fss_identify/c/fss_identify.h +++ b/level_3/fss_identify/c/fss_identify.h @@ -53,21 +53,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_identify_print_help_ - extern f_status_t fss_identify_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_identify_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -80,16 +65,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_identify_main_ - extern f_status_t fss_identify_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_identify_main(fll_program_data_t * const main, fss_identify_setting_t * const setting); #endif // _di_fss_identify_main_ #ifdef __cplusplus diff --git a/level_3/fss_identify/c/main.c b/level_3/fss_identify/c/main.c index 1b697b8..5ef29a1 100644 --- a/level_3/fss_identify/c/main.c +++ b/level_3/fss_identify/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_identify_setting_t setting = fss_identify_setting_t_initialize; f_console_parameter_t parameters[] = fss_identify_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_identify_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_identify_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_identify_setting_load(arguments, &data, &setting); + } + + fss_identify_main(&data, &setting); + + fss_identify_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_identify/c/print.c b/level_3/fss_identify/c/print.c new file mode 100644 index 0000000..36e102b --- /dev/null +++ b/level_3/fss_identify/c/print.c @@ -0,0 +1,89 @@ +#include "fss_identify.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_identify_print_help_ + f_status_t fss_identify_print_help(fss_identify_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_identify_program_name_long_s, fss_identify_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_identify_short_content_s, fss_identify_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the Identifier content (the 4-digit hexidecimal type code)."); + fll_program_print_help_option(print, fss_identify_short_object_s, fss_identify_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Identifier object (the name)."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_identify_short_line_s, fss_identify_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Identifier at the given line."); + fll_program_print_help_option(print, fss_identify_short_name_s, fss_identify_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select FSS using this full or partial type name or code."); + fll_program_print_help_option(print, fss_identify_short_total_s, fss_identify_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the total Identifiers found."); + + fll_program_print_help_usage(print, fss_identify_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r The %[%r%r%] parameter refers to the file lines and not the lines in a given file.%r%r", print.to.stream, f_string_eol_s, print.set->notable, f_console_symbol_long_enable_s, fss_identify_long_line_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" If neither the %[%r%r%] nor", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_identify_long_object_s, print.set->notable); + fl_print_format(" %[%r%r%] are specified, then the default behavior is to print both.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_identify_long_content_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying the %[%r%r%] parameter, neither the", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_identify_long_total_s, print.set->notable); + fl_print_format(" %[%r%r%] nor the", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_identify_long_object_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter may be specified.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_identify_long_content_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" An FSS file is identified by the following format: '%[# Object-Content%]'", print.to.stream, print.set->notable, print.set->notable); + fl_print_format(" where the Object, is a machine-name representing the name and may only consist of \"word\" characters and the Content is a 4-digit hexidecimal number representing a particular variant of the Object.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This identifier, if provided, must exist on the first line in a file and must begin with the pound character: '#'.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Whitespace must follow this pound character.%r", print.to.stream, f_string_eol_s); + fl_print_format(" There may be multiple Object and Content pairs, separated by white space, such as: \"# fss-0002 fss-0000 iki-0002\".%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_identify_print_help_ + +#ifndef _di_fss_identify_print_line_first_ + void fss_identify_print_line_first(fss_identify_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_identify_print_line_first_ + +#ifndef _di_fss_identify_print_line_last_ + void fss_identify_print_line_last(fss_identify_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_identify_main_flag_verify_e) return; + if ((setting->flag & fss_identify_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_identify_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_identify/c/print.h b/level_3/fss_identify/c/print.h new file mode 100644 index 0000000..437e982 --- /dev/null +++ b/level_3/fss_identify/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_identify_print_h +#define _fss_identify_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_identify_print_help_ + extern f_status_t fss_identify_print_help(fss_identify_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_identify_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_identify_print_line_first_ + extern void fss_identify_print_line_first(fss_identify_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_identify_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_identify_print_line_last_ + extern void fss_identify_print_line_last(fss_identify_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_identify_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_identify_print_h diff --git a/level_3/fss_identify/c/private-common.c b/level_3/fss_identify/c/private-common.c index 3d7aba0..e6d4b34 100644 --- a/level_3/fss_identify/c/private-common.c +++ b/level_3/fss_identify/c/private-common.c @@ -14,24 +14,6 @@ extern "C" { } #endif // _di_fss_identify_data_delete_ -#ifndef _di_fss_identify_print_signal_received_ - void fss_identify_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_identify_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/private-common.h b/level_3/fss_identify/c/private-common.h index e584f36..72491fa 100644 --- a/level_3/fss_identify/c/private-common.h +++ b/level_3/fss_identify/c/private-common.h @@ -52,16 +52,6 @@ extern "C" { extern void fss_identify_data_delete(fss_identify_data_t *data) F_attribute_visibility_internal_d; #endif // _di_fss_identify_data_delete_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_identify_print_signal_received_ - extern void fss_identify_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_identify_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_identify/c/private-identify.c b/level_3/fss_identify/c/private-identify.c index 0441ddb..2fa7c04 100644 --- a/level_3/fss_identify/c/private-identify.c +++ b/level_3/fss_identify/c/private-identify.c @@ -20,7 +20,7 @@ extern "C" { do { if (!((++main->signal_check) % fss_identify_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_identify_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_identify/data/build/settings b/level_3/fss_identify/data/build/settings index a016bd4..9797c7c 100644 --- a/level_3/fss_identify/data/build/settings +++ b/level_3/fss_identify/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_fss -lfll_print -lfll_program -lfl_ build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_identify.c common.c private-common.c private-identify.c private-print.c +build_sources_library fss_identify.c common.c print.c private-common.c private-identify.c private-print.c build_sources_program main.c -build_sources_headers fss_identify.h common.h +build_sources_headers fss_identify.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_payload_read/c/common.c b/level_3/fss_payload_read/c/common.c index 0c742fa..49fdb5d 100644 --- a/level_3/fss_payload_read/c/common.c +++ b/level_3/fss_payload_read/c/common.c @@ -52,6 +52,358 @@ extern "C" { const f_string_static_t fss_payload_read_delimit_mode_name_lesser_s = macro_f_string_static_t_initialize(FSS_PAYLOAD_READ_delimit_mode_name_lesser_s, 0, FSS_PAYLOAD_READ_delimit_mode_name_lesser_s_length); #endif // _di_fss_payload_read_delimit_mode_ +#ifndef _di_fss_payload_read_setting_delete_ + f_status_t fss_payload_read_setting_delete(fss_payload_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_payload_read_setting_delete_ + +#ifndef _di_fss_payload_read_setting_load_ + void fss_payload_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_payload_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_payload_read_parameter_no_color_e, fss_payload_read_parameter_light_e, fss_payload_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_payload_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_payload_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_payload_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_payload_read_parameter_verbosity_quiet_e, fss_payload_read_parameter_verbosity_error_e, fss_payload_read_parameter_verbosity_verbose_e, fss_payload_read_parameter_verbosity_debug_e, fss_payload_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_payload_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_payload_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_payload_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_payload_read_parameter_from_bytesequence_e, fss_payload_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_payload_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_payload_read_parameter_from_bytesequence_e) { + if (setting->mode & fss_payload_read_mode_from_codepoint_e) { + setting->mode -= fss_payload_read_mode_from_codepoint_e; + } + + setting->mode |= fss_payload_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_payload_read_parameter_from_codepoint_e) { + if (setting->mode & fss_payload_read_mode_from_bytesequence_e) { + setting->mode -= fss_payload_read_mode_from_bytesequence_e; + } + + setting->mode |= fss_payload_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_payload_read_parameter_to_bytesequence_e, fss_payload_read_parameter_to_codepoint_e, fss_payload_read_parameter_to_combining_e, fss_payload_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_payload_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_payload_read_parameter_to_bytesequence_e) { + if (setting->mode & fss_payload_read_mode_to_codepoint_e) { + setting->mode -= fss_payload_read_mode_to_codepoint_e; + } + + if (setting->mode & fss_payload_read_mode_to_combining_e) { + setting->mode -= fss_payload_read_mode_to_combining_e; + } + + if (setting->mode & fss_payload_read_mode_to_width_e) { + setting->mode -= fss_payload_read_mode_to_width_e; + } + + setting->mode |= fss_payload_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_payload_read_parameter_to_codepoint_e) { + if (setting->mode & fss_payload_read_mode_to_bytesequence_e) { + setting->mode -= fss_payload_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_payload_read_mode_to_combining_e) { + setting->mode -= fss_payload_read_mode_to_combining_e; + } + + if (setting->mode & fss_payload_read_mode_to_width_e) { + setting->mode -= fss_payload_read_mode_to_width_e; + } + + setting->mode |= fss_payload_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_payload_read_parameter_to_combining_e) { + if (setting->mode & fss_payload_read_mode_to_bytesequence_e) { + setting->mode -= fss_payload_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_payload_read_mode_to_codepoint_e) { + setting->mode -= fss_payload_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_payload_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_payload_read_mode_to_width_e; + } + + setting->mode |= fss_payload_read_mode_to_combining_e; + } + else if (choices.array[choice] == fss_payload_read_parameter_to_width_e) { + if (setting->mode & fss_payload_read_mode_to_bytesequence_e) { + setting->mode -= fss_payload_read_mode_to_bytesequence_e; + } + + if (setting->mode & fss_payload_read_mode_to_codepoint_e) { + setting->mode -= fss_payload_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_payload_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_payload_read_mode_to_combining_e; + } + + setting->mode |= fss_payload_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_payload_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_payload_read_parameter_to_file_e].values.used > 1) { + fss_payload_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_payload_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_payload_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_payload_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_payload_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_payload_read_main_flag_file_to_e; + } + else { + fss_payload_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_payload_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_payload_read_parameter_to_file_e].result == f_console_result_found_e) { + fss_payload_read_print_error_no_value(main, setting, fss_payload_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_payload_read_main_flag_file_to_e) { + setting->flag -= fss_payload_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_payload_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_payload_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_payload_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_payload_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_payload_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_payload_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_payload_read_main_flag_file_from_e; + } + else if (main->parameters.array[fss_payload_read_parameter_from_file_e].result == f_console_result_found_e) { + fss_payload_read_print_error_no_value(main, setting, fss_payload_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_payload_read_main_flag_file_from_e) { + setting->flag -= fss_payload_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_payload_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_payload_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_payload_read_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_payload_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_payload_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_payload_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_payload_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_read_main_flag_header_e; + } + + if (main->parameters.array[fss_payload_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_read_main_flag_separate_e; + } + + if (main->parameters.array[fss_payload_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_payload_read_setting_load_ + +#ifndef _di_fss_payload_read_setting_unload_ + f_status_t fss_payload_read_setting_unload(fll_program_data_t * const main, fss_payload_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_payload_read_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_payload_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_read/c/common.h b/level_3/fss_payload_read/c/common.h index 186be3c..839adb7 100644 --- a/level_3/fss_payload_read/c/common.h +++ b/level_3/fss_payload_read/c/common.h @@ -287,6 +287,132 @@ extern "C" { }; #endif // _di_fss_payload_read_delimit_modes_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_payload_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_payload_read_main_flag_e_ + enum { + fss_payload_read_main_flag_none_e = 0x0, + fss_payload_read_main_flag_file_from_e = 0x1, + fss_payload_read_main_flag_file_to_e = 0x2, + fss_payload_read_main_flag_header_e = 0x4, + fss_payload_read_main_flag_help_e = 0x8, + fss_payload_read_main_flag_separate_e = 0x10, + fss_payload_read_main_flag_strip_invalid_e = 0x20, + fss_payload_read_main_flag_verify_e = 0x40, + fss_payload_read_main_flag_version_e = 0x80, + }; +#endif // _di_fss_payload_read_main_flag_e_ + +/** + * The fss payload read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_payload_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_payload_read_setting_t; + + #define fss_payload_read_setting_t_initialize \ + { \ + fss_payload_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_payload_read_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_payload_read_setting_delete_ + extern f_status_t fss_payload_read_setting_delete(fss_payload_read_setting_t * const setting); +#endif // _di_fss_payload_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_payload_read_setting_load_ + extern void fss_payload_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_payload_read_setting_t * const setting); +#endif // _di_fss_payload_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_payload_read_setting_unload_ + extern f_status_t fss_payload_read_setting_unload(fll_program_data_t * const main, fss_payload_read_setting_t * const setting); +#endif // _di_fss_payload_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_read/c/fss_payload_read.c b/level_3/fss_payload_read/c/fss_payload_read.c index 01cfa0c..4b536ae 100644 --- a/level_3/fss_payload_read/c/fss_payload_read.c +++ b/level_3/fss_payload_read/c/fss_payload_read.c @@ -16,129 +16,8 @@ extern "C" { const f_string_static_t fss_payload_read_program_name_long_s = macro_f_string_static_t_initialize(FSS_PAYLOAD_READ_program_name_long_s, 0, FSS_PAYLOAD_READ_program_name_long_s_length); #endif // _di_fss_payload_read_program_name_ -#ifndef _di_fss_payload_read_print_help_ - f_status_t fss_payload_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_payload_read_program_name_long_s, fss_payload_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_payload_read_short_at_s, fss_payload_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); - fll_program_print_help_option(file, context, fss_payload_read_short_content_s, fss_payload_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); - fll_program_print_help_option(file, context, fss_payload_read_short_columns_s, fss_payload_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); - fll_program_print_help_option(file, context, fss_payload_read_short_delimit_s, fss_payload_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); - fll_program_print_help_option(file, context, fss_payload_read_short_depth_s, fss_payload_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); - fll_program_print_help_option(file, context, fss_payload_read_short_empty_s, fss_payload_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); - fll_program_print_help_option(file, context, fss_payload_read_short_line_s, fss_payload_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); - fll_program_print_help_option(file, context, fss_payload_read_short_name_s, fss_payload_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); - fll_program_print_help_option(file, context, fss_payload_read_short_object_s, fss_payload_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); - fll_program_print_help_option(file, context, fss_payload_read_short_pipe_s, fss_payload_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); - fll_program_print_help_option(file, context, fss_payload_read_short_original_s, fss_payload_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); - fll_program_print_help_option(file, context, fss_payload_read_short_select_s, fss_payload_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); - fll_program_print_help_option(file, context, fss_payload_read_short_total_s, fss_payload_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); - fll_program_print_help_option(file, context, fss_payload_read_short_trim_s, fss_payload_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); - - fll_program_print_help_usage(file, context, fss_payload_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - - fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-000E Payload standard.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", file.stream, f_string_eol_s); - fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, context.set.notable, f_string_eol_s); - - fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", file.stream, f_string_eol_s); - - fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_at_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, context.set.notable, f_string_eol_s); - fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", file.stream, f_string_eol_s); - fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" Specify both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_object_s, context.set.notable); - fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_total_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When both %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_at_s, context.set.notable); - fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_name_s, context.set.notable); - fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_at_s, context.set.notable); - fl_print_format(" %[%r%r%] parameter value.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_name_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program may support parameters, such as %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, context.set.notable); - fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, context.set.notable, f_string_eol_s); - fl_print_format(" This is done to help ensure consistency for scripting.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, context.set.notable); - fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", file.stream, f_string_eol_s); - - fl_print_format(" For parameters like %[%r%r%],", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, context.set.notable); - fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_trim_s, context.set.notable); - fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When specifying both the %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_object_s, context.set.notable); - fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_content_s, context.set.notable, f_string_eol_s); - fl_print_format(" Both the Object and Content printed are already escaped.%r", file.stream, f_string_eol_s); - fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameter %[%r%r%] accepts the following:%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_delimit_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Do not apply delimits.%r", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_none_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_all_s, context.set.notable, f_string_eol_s); - fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_object_s, context.set.notable, f_string_eol_s); - fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", file.stream, f_string_eol_s); - fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_greater_s, context.set.notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_lesser_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_delimit_s, context.set.notable, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_delimit_s, context.set.notable); - fl_print_format(" values %[%r%]", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_none_s, context.set.notable); - fl_print_format(" and %[%r%],", file.stream, context.set.notable, fss_payload_read_delimit_mode_name_all_s, context.set.notable); - fl_print_format(" overrule all other delimit values.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The parameters %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_columns_s, context.set.notable); - fl_print_format(" and %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, context.set.notable); - fl_print_format(" refer to a Content column.%r", file.stream, f_string_eol_s); - fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", file.stream, f_string_eol_s); - fl_print_format(" This is not to be confused with a depth.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" As an exceptional case, a %[%r%r%] of", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, context.set.notable); - fl_print_format(" %[1%] applies only to the explicit Object of", file.stream, context.set.notable, context.set.notable); - fl_print_format(" '%[%r%]'.%r", file.stream, context.set.notable, f_fss_string_header_s, context.set.notable, f_string_eol_s); - fl_print_format(" Content at this depth is processed as FSS-0001 Extended.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The Content of the explicit Object of", file.stream); - fl_print_format(" '%[%r%]'", file.stream, context.set.notable, f_fss_string_payload_s, context.set.notable, f_string_eol_s); - fl_print_format(" will not contain any Content close pipe control codes when using", file.stream); - fl_print_format(" %[%r%r%].%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_read_long_pipe_s, context.set.notable, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_payload_read_print_help_ - #ifndef _di_fss_payload_read_main_ - f_status_t fss_payload_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_payload_read_main(fll_program_data_t * const main, fss_payload_read_setting_t * const setting) { f_status_t status = F_none; @@ -188,13 +67,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_payload_read_parameter_help_e].result == f_console_result_found_e) { - fss_payload_read_print_help(main->output.to, main->context); + fss_payload_read_print_help(setting, main->message); return status; } if (main->parameters.array[fss_payload_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_payload_read_program_version_s); + fll_program_print_version(main->message, fss_payload_read_program_version_s); return status; } @@ -328,7 +207,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -546,7 +425,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -612,7 +491,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > fss_payload_read_block_max && fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_payload_read/c/fss_payload_read.h b/level_3/fss_payload_read/c/fss_payload_read.h index 1aaca7e..237c49c 100644 --- a/level_3/fss_payload_read/c/fss_payload_read.h +++ b/level_3/fss_payload_read/c/fss_payload_read.h @@ -56,21 +56,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_payload_read_print_help_ - extern f_status_t fss_payload_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_payload_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -92,7 +77,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_fss_payload_read_main_ - extern f_status_t fss_payload_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_payload_read_main(fll_program_data_t * const main, fss_payload_read_setting_t * const setting); #endif // _di_fss_payload_read_main_ #ifdef __cplusplus diff --git a/level_3/fss_payload_read/c/main.c b/level_3/fss_payload_read/c/main.c index c4e4387..1fa6db4 100644 --- a/level_3/fss_payload_read/c/main.c +++ b/level_3/fss_payload_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_payload_read_setting_t setting = fss_payload_read_setting_t_initialize; f_console_parameter_t parameters[] = fss_payload_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_payload_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_payload_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_payload_read_setting_load(arguments, &data, &setting); + } + + fss_payload_read_main(&data, &setting); + + fss_payload_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_payload_read/c/print.c b/level_3/fss_payload_read/c/print.c new file mode 100644 index 0000000..5bb4951 --- /dev/null +++ b/level_3/fss_payload_read/c/print.c @@ -0,0 +1,158 @@ +#include "fss_payload_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_payload_read_print_help_ + f_status_t fss_payload_read_print_help(fss_payload_read_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_payload_read_program_name_long_s, fss_payload_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_payload_read_short_at_s, fss_payload_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric index."); + fll_program_print_help_option(print, fss_payload_read_short_content_s, fss_payload_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Content (default)."); + fll_program_print_help_option(print, fss_payload_read_short_columns_s, fss_payload_read_long_columns_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of columns."); + fll_program_print_help_option(print, fss_payload_read_short_delimit_s, fss_payload_read_long_delimit_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Designate how to handle applying delimits."); + fll_program_print_help_option(print, fss_payload_read_short_depth_s, fss_payload_read_long_depth_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object at this numeric depth."); + fll_program_print_help_option(print, fss_payload_read_short_empty_s, fss_payload_read_long_empty_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Include empty Content when processing."); + fll_program_print_help_option(print, fss_payload_read_short_line_s, fss_payload_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the Content at the given line."); + fll_program_print_help_option(print, fss_payload_read_short_name_s, fss_payload_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select Object with this name."); + fll_program_print_help_option(print, fss_payload_read_short_object_s, fss_payload_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the Object."); + fll_program_print_help_option(print, fss_payload_read_short_pipe_s, fss_payload_read_long_pipe_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print using the special pipe format."); + fll_program_print_help_option(print, fss_payload_read_short_original_s, fss_payload_read_long_original_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print with the original quotes and escapes."); + fll_program_print_help_option(print, fss_payload_read_short_select_s, fss_payload_read_long_select_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select sub-Content at this index."); + fll_program_print_help_option(print, fss_payload_read_short_total_s, fss_payload_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of lines."); + fll_program_print_help_option(print, fss_payload_read_short_trim_s, fss_payload_read_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names on select or print."); + + fll_program_print_help_usage(print, fss_payload_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + + fl_print_format(" This program will print the Content associated with the given Object and Content main based on the FSS-000E Payload standard.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" All numeric positions (indexes) start at 0 instead of 1.%r", print.to.stream, f_string_eol_s); + fl_print_format(" For example, a file of 17 lines would range from 0 to 16.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When using the %[%r%r%] option, an order of operations is enforced on the parameters.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, print.set->notable, f_string_eol_s); + + fl_print_format(" When this order of operations is in effect, parameters to the right of a depth parameter are influenced by that depth parameter:%r", print.to.stream, f_string_eol_s); + + fl_print_format(" %[%r%r%]: An Object index at the specified depth.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_at_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: A new depth within the specified depth, indexed from the root.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%r%]: An Object name at the specified depth.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] must be in numeric order, but values in between may be skipped.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, print.set->notable, f_string_eol_s); + fl_print_format(" ('-d 0 -a 1 -d 2 -a 2' would specify index 1 at depth 0, any index at depth 1, and index 2 at depth 2.)%r", print.to.stream, f_string_eol_s); + fl_print_format(" ('-d 2 -a 1 -d 0 -a 2' would be invalid because depth 2 is before depth 1.)%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] selects a Content column.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" Specify both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_object_s, print.set->notable); + fl_print_format(" and the %[%r%r%] parameters to get the total objects.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_total_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When both %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_at_s, print.set->notable); + fl_print_format(" and %[%r%r%] parameters are specified (at the same depth),", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_name_s, print.set->notable); + fl_print_format(" the %[%r%r%] parameter value will be treated as a position relative to the specified", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_at_s, print.set->notable); + fl_print_format(" %[%r%r%] parameter value.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_name_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program may support parameters, such as %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, print.set->notable); + fl_print_format(" or %[%r%r%], even if not supported by the standard.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, print.set->notable, f_string_eol_s); + fl_print_format(" This is done to help ensure consistency for scripting.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, print.set->notable); + fl_print_format(" if the standard doesn't support nested Content, then only a depth of 0 would be valid.%r", print.to.stream, f_string_eol_s); + + fl_print_format(" For parameters like %[%r%r%],", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, print.set->notable); + fl_print_format(" if the standard doesn't support multiple Content groups, then only a select of 0 would be valid.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_trim_s, print.set->notable); + fl_print_format(" will remove leading and trailing white spaces when selecting objects or when printing objects.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When specifying both the %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_object_s, print.set->notable); + fl_print_format(" parameter and the %[%r%r%] parameter, the entire Object and Content are printed, including the formatting.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_content_s, print.set->notable, f_string_eol_s); + fl_print_format(" Both the Object and Content printed are already escaped.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Both the Object and Content are separated by a New Line character '\\n' (U+000A).%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameter %[%r%r%] accepts the following:%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_delimit_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Do not apply delimits.%r", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_none_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: (default) Apply all delimits.%r", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_all_s, print.set->notable, f_string_eol_s); + fl_print_format(" - %[%r%]: Apply delimits for Objects.%r", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_object_s, print.set->notable, f_string_eol_s); + fl_print_format(" - A number, 0 or greater: apply delimits for Content at the specified depth.%r", print.to.stream, f_string_eol_s); + fl_print_format(" - A number, 0 or greater, followed by a %[%r%]: (such as '1+') apply delimits for Content at the specified depth and any greater depth (numerically).%r", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_greater_s, print.set->notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" - A number, 0 or lesser, followed by a %[%r%]: (such as '1-') apply delimits for Content at the specified depth and any lesser depth (numerically).%r%r", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_lesser_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] parameter may be specified multiple times to customize the delimit behavior.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_delimit_s, print.set->notable, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_delimit_s, print.set->notable); + fl_print_format(" values %[%r%]", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_none_s, print.set->notable); + fl_print_format(" and %[%r%],", print.to.stream, print.set->notable, fss_payload_read_delimit_mode_name_all_s, print.set->notable); + fl_print_format(" overrule all other delimit values.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The parameters %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_columns_s, print.set->notable); + fl_print_format(" and %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_select_s, print.set->notable); + fl_print_format(" refer to a Content column.%r", print.to.stream, f_string_eol_s); + fl_print_format(" The word \"column\" is being loosely defined to refer to a specific Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" This is not to be confused with a depth.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" As an exceptional case, a %[%r%r%] of", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_depth_s, print.set->notable); + fl_print_format(" %[1%] applies only to the explicit Object of", print.to.stream, print.set->notable, print.set->notable); + fl_print_format(" '%[%r%]'.%r", print.to.stream, print.set->notable, f_fss_string_header_s, print.set->notable, f_string_eol_s); + fl_print_format(" Content at this depth is processed as FSS-0001 Extended.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The Content of the explicit Object of", print.to.stream); + fl_print_format(" '%[%r%]'", print.to.stream, print.set->notable, f_fss_string_payload_s, print.set->notable, f_string_eol_s); + fl_print_format(" will not contain any Content close pipe control codes when using", print.to.stream); + fl_print_format(" %[%r%r%].%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_read_long_pipe_s, print.set->notable, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_payload_read_print_help_ + +#ifndef _di_fss_payload_read_print_line_first_ + void fss_payload_read_print_line_first(fss_payload_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_payload_read_print_line_first_ + +#ifndef _di_fss_payload_read_print_line_last_ + void fss_payload_read_print_line_last(fss_payload_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_payload_read_main_flag_verify_e) return; + if ((setting->flag & fss_payload_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_payload_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_payload_read/c/print.h b/level_3/fss_payload_read/c/print.h new file mode 100644 index 0000000..5b44116 --- /dev/null +++ b/level_3/fss_payload_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_payload_read_print_h +#define _fss_payload_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_payload_read_print_help_ + extern f_status_t fss_payload_read_print_help(fss_payload_read_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_payload_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_payload_read_print_line_first_ + extern void fss_payload_read_print_line_first(fss_payload_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_payload_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_payload_read_print_line_last_ + extern void fss_payload_read_print_line_last(fss_payload_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_payload_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_payload_read_print_h diff --git a/level_3/fss_payload_read/c/private-common.c b/level_3/fss_payload_read/c/private-common.c index 7816a6d..7ba3183 100644 --- a/level_3/fss_payload_read/c/private-common.c +++ b/level_3/fss_payload_read/c/private-common.c @@ -62,24 +62,6 @@ extern "C" { } #endif // _di_fss_payload_read_depths_resize_ -#ifndef _di_fss_payload_read_print_signal_received_ - void fss_payload_read_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_payload_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_read/c/private-common.h b/level_3/fss_payload_read/c/private-common.h index c19e859..e52f234 100644 --- a/level_3/fss_payload_read/c/private-common.h +++ b/level_3/fss_payload_read/c/private-common.h @@ -281,16 +281,6 @@ extern "C" { extern f_status_t fss_payload_read_depths_resize(const f_array_length_t length, fss_payload_read_depths_t *depths) F_attribute_visibility_internal_d; #endif // _di_fss_payload_read_depths_resize_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_payload_read_print_signal_received_ - extern void fss_payload_read_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_payload_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_read/c/private-read.c b/level_3/fss_payload_read/c/private-read.c index 36e0da4..d99d35d 100644 --- a/level_3/fss_payload_read/c/private-read.c +++ b/level_3/fss_payload_read/c/private-read.c @@ -88,7 +88,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -176,7 +176,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -454,7 +454,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -505,7 +505,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -708,7 +708,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -791,7 +791,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -861,7 +861,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } @@ -1066,7 +1066,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_read_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); return F_status_set_error(F_interrupt); } diff --git a/level_3/fss_payload_read/data/build/settings b/level_3/fss_payload_read/data/build/settings index cb89eb0..94ca06f 100644 --- a/level_3/fss_payload_read/data/build/settings +++ b/level_3/fss_payload_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_payload_read.c common.c private-common.c private-print.c private-read.c +build_sources_library fss_payload_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers fss_payload_read.h common.h +build_sources_headers fss_payload_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_payload_write/c/common.c b/level_3/fss_payload_write/c/common.c index 6d321da..84a5dcf 100644 --- a/level_3/fss_payload_write/c/common.c +++ b/level_3/fss_payload_write/c/common.c @@ -32,6 +32,358 @@ extern "C" { const f_string_static_t fss_payload_write_long_trim_s = macro_f_string_static_t_initialize(FSS_PAYLOAD_WRITE_long_trim_s, 0, FSS_PAYLOAD_WRITE_long_trim_s_length); #endif // _di_fss_payload_write_parameters_ +#ifndef _di_fss_payload_write_setting_delete_ + f_status_t fss_payload_write_setting_delete(fss_payload_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_payload_write_setting_delete_ + +#ifndef _di_fss_payload_write_setting_load_ + void fss_payload_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_payload_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_payload_write_parameter_no_color_e, fss_payload_write_parameter_light_e, fss_payload_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_payload_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[fss_payload_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_payload_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_payload_write_parameter_verbosity_quiet_e, fss_payload_write_parameter_verbosity_error_e, fss_payload_write_parameter_verbosity_verbose_e, fss_payload_write_parameter_verbosity_debug_e, fss_payload_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_payload_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[fss_payload_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_payload_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { fss_payload_write_parameter_from_bytesequence_e, fss_payload_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_payload_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_payload_write_parameter_from_bytesequence_e) { + if (setting->mode & fss_payload_write_mode_from_codepoint_e) { + setting->mode -= fss_payload_write_mode_from_codepoint_e; + } + + setting->mode |= fss_payload_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == fss_payload_write_parameter_from_codepoint_e) { + if (setting->mode & fss_payload_write_mode_from_bytesequence_e) { + setting->mode -= fss_payload_write_mode_from_bytesequence_e; + } + + setting->mode |= fss_payload_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { fss_payload_write_parameter_to_bytesequence_e, fss_payload_write_parameter_to_codepoint_e, fss_payload_write_parameter_to_combining_e, fss_payload_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + fss_payload_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == fss_payload_write_parameter_to_bytesequence_e) { + if (setting->mode & fss_payload_write_mode_to_codepoint_e) { + setting->mode -= fss_payload_write_mode_to_codepoint_e; + } + + if (setting->mode & fss_payload_write_mode_to_combining_e) { + setting->mode -= fss_payload_write_mode_to_combining_e; + } + + if (setting->mode & fss_payload_write_mode_to_width_e) { + setting->mode -= fss_payload_write_mode_to_width_e; + } + + setting->mode |= fss_payload_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == fss_payload_write_parameter_to_codepoint_e) { + if (setting->mode & fss_payload_write_mode_to_bytesequence_e) { + setting->mode -= fss_payload_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_payload_write_mode_to_combining_e) { + setting->mode -= fss_payload_write_mode_to_combining_e; + } + + if (setting->mode & fss_payload_write_mode_to_width_e) { + setting->mode -= fss_payload_write_mode_to_width_e; + } + + setting->mode |= fss_payload_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == fss_payload_write_parameter_to_combining_e) { + if (setting->mode & fss_payload_write_mode_to_bytesequence_e) { + setting->mode -= fss_payload_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_payload_write_mode_to_codepoint_e) { + setting->mode -= fss_payload_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_payload_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= fss_payload_write_mode_to_width_e; + } + + setting->mode |= fss_payload_write_mode_to_combining_e; + } + else if (choices.array[choice] == fss_payload_write_parameter_to_width_e) { + if (setting->mode & fss_payload_write_mode_to_bytesequence_e) { + setting->mode -= fss_payload_write_mode_to_bytesequence_e; + } + + if (setting->mode & fss_payload_write_mode_to_codepoint_e) { + setting->mode -= fss_payload_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[fss_payload_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= fss_payload_write_mode_to_combining_e; + } + + setting->mode |= fss_payload_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[fss_payload_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[fss_payload_write_parameter_to_file_e].values.used > 1) { + fss_payload_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[fss_payload_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[fss_payload_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[fss_payload_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[fss_payload_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= fss_payload_write_main_flag_file_to_e; + } + else { + fss_payload_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[fss_payload_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[fss_payload_write_parameter_to_file_e].result == f_console_result_found_e) { + fss_payload_write_print_error_no_value(main, setting, fss_payload_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & fss_payload_write_main_flag_file_to_e) { + setting->flag -= fss_payload_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[fss_payload_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[fss_payload_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[fss_payload_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[fss_payload_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + fss_payload_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + fss_payload_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= fss_payload_write_main_flag_file_from_e; + } + else if (main->parameters.array[fss_payload_write_parameter_from_file_e].result == f_console_result_found_e) { + fss_payload_write_print_error_no_value(main, setting, fss_payload_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & fss_payload_write_main_flag_file_from_e) { + setting->flag -= fss_payload_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[fss_payload_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + fss_payload_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & fss_payload_write_mode_to_bytesequence_e)) { + if (main->parameters.array[fss_payload_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[fss_payload_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = fss_payload_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[fss_payload_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_write_main_flag_header_e; + } + + if (main->parameters.array[fss_payload_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_write_main_flag_separate_e; + } + + if (main->parameters.array[fss_payload_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= fss_payload_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_fss_payload_write_setting_load_ + +#ifndef _di_fss_payload_write_setting_unload_ + f_status_t fss_payload_write_setting_unload(fll_program_data_t * const main, fss_payload_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_payload_write_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_payload_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_write/c/common.h b/level_3/fss_payload_write/c/common.h index 5f8126f..b9094eb 100644 --- a/level_3/fss_payload_write/c/common.h +++ b/level_3/fss_payload_write/c/common.h @@ -196,6 +196,132 @@ extern "C" { #define fss_payload_write_total_parameters_d 21 #endif // _di_fss_payload_write_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * fss_payload_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_fss_payload_write_main_flag_e_ + enum { + fss_payload_write_main_flag_none_e = 0x0, + fss_payload_write_main_flag_file_from_e = 0x1, + fss_payload_write_main_flag_file_to_e = 0x2, + fss_payload_write_main_flag_header_e = 0x4, + fss_payload_write_main_flag_help_e = 0x8, + fss_payload_write_main_flag_separate_e = 0x10, + fss_payload_write_main_flag_strip_invalid_e = 0x20, + fss_payload_write_main_flag_verify_e = 0x40, + fss_payload_write_main_flag_version_e = 0x80, + }; +#endif // _di_fss_payload_write_main_flag_e_ + +/** + * The fss payload write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_payload_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_payload_write_setting_t; + + #define fss_payload_write_setting_t_initialize \ + { \ + fss_payload_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_payload_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_payload_write_setting_delete_ + extern f_status_t fss_payload_write_setting_delete(fss_payload_write_setting_t * const setting); +#endif // _di_fss_payload_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_payload_write_setting_load_ + extern void fss_payload_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_payload_write_setting_t * const setting); +#endif // _di_fss_payload_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_payload_write_setting_unload_ + extern f_status_t fss_payload_write_setting_unload(fll_program_data_t * const main, fss_payload_write_setting_t * const setting); +#endif // _di_fss_payload_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_write/c/fss_payload_write.c b/level_3/fss_payload_write/c/fss_payload_write.c index 1cc34ec..0669bb8 100644 --- a/level_3/fss_payload_write/c/fss_payload_write.c +++ b/level_3/fss_payload_write/c/fss_payload_write.c @@ -15,59 +15,8 @@ extern "C" { const f_string_static_t fss_payload_write_program_name_long_s = macro_f_string_static_t_initialize(FSS_PAYLOAD_WRITE_program_name_long_s, 0, FSS_PAYLOAD_WRITE_program_name_long_s_length); #endif // _di_fss_payload_write_program_name_ -#ifndef _di_fss_payload_write_print_help_ - f_status_t fss_payload_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_payload_write_program_name_long_s, fss_payload_write_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_payload_write_short_file_s, fss_payload_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, fss_payload_write_short_content_s, fss_payload_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, fss_payload_write_short_double_s, fss_payload_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, fss_payload_write_short_ignore_s, fss_payload_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); - fll_program_print_help_option(file, context, fss_payload_write_short_object_s, fss_payload_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, fss_payload_write_short_partial_s, fss_payload_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); - fll_program_print_help_option(file, context, fss_payload_write_short_prepend_s, fss_payload_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); - fll_program_print_help_option(file, context, fss_payload_write_short_single_s, fss_payload_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - fll_program_print_help_option(file, context, fss_payload_write_short_trim_s, fss_payload_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); - - fll_program_print_help_usage(file, context, fss_payload_write_program_name_s, f_string_empty_s); - - fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", file.stream, f_string_eol_s, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable); - fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", file.stream, context.set.notable, context.set.notable, context.set.notable, context.set.notable, f_string_eol_s); - fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The FSS-000E (Payload) specification does not support quoted names, therefore the parameters '%[%r%r%]'", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_write_long_single_s, context.set.notable); - fl_print_format(" and '%[%r%r%]' do nothing.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_write_long_double_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, fss_payload_write_long_ignore_s, context.set.notable, f_string_eol_s); - fl_print_format(" This parameter requires two values.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_payload_write_print_help_ - #ifndef _di_fss_payload_write_main_ - f_status_t fss_payload_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t fss_payload_write_main(fll_program_data_t * const main, fss_payload_write_setting_t * const setting) { f_status_t status = F_none; @@ -119,13 +68,13 @@ extern "C" { status = F_none; if (main->parameters.array[fss_payload_write_parameter_help_e].result == f_console_result_found_e) { - fss_payload_write_print_help(main->output.to, main->context); + fss_payload_write_print_help(setting, main->message); return status; } if (main->parameters.array[fss_payload_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_payload_write_program_version_s); + fll_program_print_version(main->message, fss_payload_write_program_version_s); return status; } @@ -416,7 +365,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -435,7 +384,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -455,7 +404,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_payload_write/c/fss_payload_write.h b/level_3/fss_payload_write/c/fss_payload_write.h index da56d81..1f64019 100644 --- a/level_3/fss_payload_write/c/fss_payload_write.h +++ b/level_3/fss_payload_write/c/fss_payload_write.h @@ -48,21 +48,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_payload_write_print_help_ - extern f_status_t fss_payload_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_payload_write_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -75,16 +60,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_payload_write_main_ - extern f_status_t fss_payload_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t fss_payload_write_main(fll_program_data_t * const main, fss_payload_write_setting_t * const setting); #endif // _di_fss_payload_write_main_ #ifdef __cplusplus diff --git a/level_3/fss_payload_write/c/main.c b/level_3/fss_payload_write/c/main.c index 5a9452c..e964989 100644 --- a/level_3/fss_payload_write/c/main.c +++ b/level_3/fss_payload_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_payload_write_setting_t setting = fss_payload_write_setting_t_initialize; f_console_parameter_t parameters[] = fss_payload_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_payload_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_payload_write_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_payload_write_setting_load(arguments, &data, &setting); + } + + fss_payload_write_main(&data, &setting); + + fss_payload_write_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/fss_payload_write/c/print.c b/level_3/fss_payload_write/c/print.c new file mode 100644 index 0000000..91f5ca5 --- /dev/null +++ b/level_3/fss_payload_write/c/print.c @@ -0,0 +1,88 @@ +#include "fss_payload_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_payload_write_print_help_ + f_status_t fss_payload_write_print_help(fss_payload_write_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_payload_write_program_name_long_s, fss_payload_write_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_payload_write_short_file_s, fss_payload_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, fss_payload_write_short_content_s, fss_payload_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, fss_payload_write_short_double_s, fss_payload_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, fss_payload_write_short_ignore_s, fss_payload_write_long_ignore_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Ignore a given range within a Content."); + fll_program_print_help_option(print, fss_payload_write_short_object_s, fss_payload_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, fss_payload_write_short_partial_s, fss_payload_write_long_partial_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Do not write end of Object/Content character."); + fll_program_print_help_option(print, fss_payload_write_short_prepend_s, fss_payload_write_long_prepend_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Prepend the given white space characters to the start of each multi-line Content."); + fll_program_print_help_option(print, fss_payload_write_short_single_s, fss_payload_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + fll_program_print_help_option(print, fss_payload_write_short_trim_s, fss_payload_write_long_trim_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Trim Object names."); + + fll_program_print_help_usage(print, fss_payload_write_program_name_s, f_string_empty_s); + + fl_print_format("%r The pipe uses the Backspace character '%[\\b%]' (%[U+0008%]) to designate the start of a Content.%r", print.to.stream, f_string_eol_s, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Form Feed character '%[\\f%]' (%[U+000C%]) to designate the end of the last Content.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The pipe uses the Vertical Line character '%[\\v%]' (%[U+000B%]) is used to ignore a Content range, which does nothing in this program.%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" For the pipe, an Object is terminated by either a Backspace character '%[\\b%]' (%[U+0008%])", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable); + fl_print_format(" or a Form Feed character '%[\\f%]' (%[U+000C%]).%r", print.to.stream, print.set->notable, print.set->notable, print.set->notable, print.set->notable, f_string_eol_s); + fl_print_format(" The end of the pipe represents the end of any Object or Content.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The FSS-000E (Payload) specification does not support quoted names, therefore the parameters '%[%r%r%]'", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_write_long_single_s, print.set->notable); + fl_print_format(" and '%[%r%r%]' do nothing.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_write_long_double_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" This program does not use the parameter '%[%r%r%]', which therefore does nothing.%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, fss_payload_write_long_ignore_s, print.set->notable, f_string_eol_s); + fl_print_format(" This parameter requires two values.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_payload_write_print_help_ + +#ifndef _di_fss_payload_write_print_line_first_ + void fss_payload_write_print_line_first(fss_payload_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_payload_write_print_line_first_ + +#ifndef _di_fss_payload_write_print_line_last_ + void fss_payload_write_print_line_last(fss_payload_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & fss_payload_write_main_flag_verify_e) return; + if ((setting->flag & fss_payload_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_payload_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_payload_write/c/print.h b/level_3/fss_payload_write/c/print.h new file mode 100644 index 0000000..b2fb19a --- /dev/null +++ b/level_3/fss_payload_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_payload_write_print_h +#define _fss_payload_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_payload_write_print_help_ + extern f_status_t fss_payload_write_print_help(fss_payload_write_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_payload_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_payload_write_print_line_first_ + extern void fss_payload_write_print_line_first(fss_payload_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_payload_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_payload_write_print_line_last_ + extern void fss_payload_write_print_line_last(fss_payload_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_payload_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_payload_write_print_h diff --git a/level_3/fss_payload_write/c/private-common.c b/level_3/fss_payload_write/c/private-common.c index 87bff85..33626b5 100644 --- a/level_3/fss_payload_write/c/private-common.c +++ b/level_3/fss_payload_write/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_payload_write_print_signal_received_ - void fss_payload_write_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_payload_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_write/c/private-common.h b/level_3/fss_payload_write/c/private-common.h index 51b2001..1262946 100644 --- a/level_3/fss_payload_write/c/private-common.h +++ b/level_3/fss_payload_write/c/private-common.h @@ -24,16 +24,6 @@ extern "C" { #define fss_payload_write_common_allocation_small_d 128 #endif // _di_fss_payload_write_common_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_payload_write_print_signal_received_ - extern void fss_payload_write_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_payload_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_payload_write/c/private-write.c b/level_3/fss_payload_write/c/private-write.c index 964cc9b..3b93b2a 100644 --- a/level_3/fss_payload_write/c/private-write.c +++ b/level_3/fss_payload_write/c/private-write.c @@ -211,7 +211,7 @@ extern "C" { if (!((++main->signal_check) % fss_payload_write_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_payload_write_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/fss_payload_write/data/build/settings b/level_3/fss_payload_write/data/build/settings index 84c0b5a..e661405 100644 --- a/level_3/fss_payload_write/data/build/settings +++ b/level_3/fss_payload_write/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_print -lfll_pr build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_payload_write.c common.c private-common.c private-write.c +build_sources_library fss_payload_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers fss_payload_write.h common.h +build_sources_headers fss_payload_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/fss_status_code/c/common.c b/level_3/fss_status_code/c/common.c index c6e73aa..0d5f548 100644 --- a/level_3/fss_status_code/c/common.c +++ b/level_3/fss_status_code/c/common.c @@ -17,6 +17,16 @@ extern "C" { const f_string_static_t fss_status_code_program_help_parameters_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_program_help_parameters_s, 0, FSS_STATUS_CODE_program_help_parameters_s_length); #endif // _di_fss_status_code_program_help_parameters_ +#ifndef _di_fss_status_code_strings_ + const f_string_static_t fss_status_code_failed_to_convert_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_failed_to_convert_s, 0, FSS_STATUS_CODE_failed_to_convert_s_length); + const f_string_static_t fss_status_code_invalid_number_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_invalid_number_s, 0, FSS_STATUS_CODE_invalid_number_s_length); + const f_string_static_t fss_status_code_invalid_name_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_invalid_number_s, 0, FSS_STATUS_CODE_invalid_number_s_length); + const f_string_static_t fss_status_code_invalid_main_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_invalid_main_s, 0, FSS_STATUS_CODE_invalid_main_s_length); + const f_string_static_t fss_status_code_out_of_range_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_out_of_range_s, 0, FSS_STATUS_CODE_out_of_range_s_length); + const f_string_static_t fss_status_code_unknown_code_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_unknown_code_s, 0, FSS_STATUS_CODE_unknown_code_s_length); + const f_string_static_t fss_status_code_unknown_name_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_unknown_name_s, 0, FSS_STATUS_CODE_unknown_name_s_length); +#endif // _di_fss_status_code_strings_ + #ifndef _di_fss_status_code_parameters_ const f_string_static_t fss_status_code_short_fine_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_short_fine_s, 0, FSS_STATUS_CODE_short_fine_s_length); const f_string_static_t fss_status_code_short_warning_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_short_warning_s, 0, FSS_STATUS_CODE_short_warning_s_length); @@ -29,6 +39,165 @@ extern "C" { const f_string_static_t fss_status_code_long_number_s = macro_f_string_static_t_initialize(FSS_STATUS_CODE_long_number_s, 0, FSS_STATUS_CODE_long_number_s_length); #endif // _di_fss_status_code_parameters_ +#ifndef _di_fss_status_code_setting_delete_ + f_status_t fss_status_code_setting_delete(fss_status_code_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_fss_status_code_setting_delete_ + +#ifndef _di_fss_status_code_setting_load_ + void fss_status_code_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_status_code_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { fss_status_code_parameter_no_color_e, fss_status_code_parameter_light_e, fss_status_code_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_status_code_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + fss_status_code_print_line_last(setting, main->error, F_true); + + return; + } + } + + if (main->parameters.array[fss_status_code_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[fss_status_code_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { fss_status_code_parameter_verbosity_quiet_e, fss_status_code_parameter_verbosity_error_e, fss_status_code_parameter_verbosity_verbose_e, fss_status_code_parameter_verbosity_debug_e, fss_status_code_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + fss_status_code_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + fss_status_code_print_line_last(setting, main->error, F_true); + + return; + } + } + + if (main->parameters.array[fss_status_code_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= fss_status_code_main_flag_help_e; + + return; + } + + if (main->parameters.array[fss_status_code_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= fss_status_code_main_flag_version_e; + + return; + } + } + + if (main->parameters.array[fss_status_code_parameter_error_e].result == f_console_result_found_e) { + setting->flag |= fss_status_code_main_flag_error_e; + } + + if (main->parameters.array[fss_status_code_parameter_fine_e].result == f_console_result_found_e) { + setting->flag |= fss_status_code_main_flag_fine_e; + } + + if (main->parameters.array[fss_status_code_parameter_warning_e].result == f_console_result_found_e) { + setting->flag |= fss_status_code_main_flag_warning_e; + } + + if (main->parameters.array[fss_status_code_parameter_number_e].result == f_console_result_found_e) { + setting->flag |= fss_status_code_main_flag_number_e; + } + + if (setting->flag & fss_status_code_main_flag_error_e) { + if (setting->flag & fss_status_code_main_flag_warning_e) { + if (!(setting->flag & fss_status_code_main_flag_number_e)) { + fss_status_code_print_line_first(setting, main->error, F_true); + fss_status_code_print_error_cannot_error_warning_number(setting, main->error); + fss_status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + + if (setting->flag & fss_status_code_main_flag_fine_e) { + fss_status_code_print_line_first(setting, main->error, F_true); + fll_program_parameter_long_print_cannot_use_with(main->error, fss_status_code_long_error_s, fss_status_code_long_fine_s); + fss_status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (setting->flag & fss_status_code_main_flag_warning_e && setting->flag & fss_status_code_main_flag_fine_e) { + fss_status_code_print_line_first(setting, main->error, F_true); + fll_program_parameter_long_print_cannot_use_with(main->error, fss_status_code_long_warning_s, fss_status_code_long_fine_s); + fss_status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (main->parameters.remaining.used == 0 && !(main->pipe & fll_program_data_pipe_input_e)) { + fss_status_code_print_line_first(setting, main->error, F_true); + fss_status_code_print_error_no_fss_status_codes(setting, main->error); + fss_status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } +#endif // _di_fss_status_code_setting_load_ + +#ifndef _di_fss_status_code_setting_unload_ + f_status_t fss_status_code_setting_unload(fll_program_data_t * const main, fss_status_code_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + fss_status_code_setting_delete(setting); + + return F_none; + } +#endif // _di_fss_status_code_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_status_code/c/common.h b/level_3/fss_status_code/c/common.h index 5f531b7..690917f 100644 --- a/level_3/fss_status_code/c/common.h +++ b/level_3/fss_status_code/c/common.h @@ -1,7 +1,7 @@ /** * FLL - Level 3 * - * Project: FSS Status code + * Project: FSS Status Code * API Version: 0.7 * Licenses: lgpl-2.1-or-later * @@ -70,6 +70,35 @@ extern "C" { #endif // _di_fss_status_code_program_help_parameters_ /** + * Special strings used by this program. + */ +#ifndef _di_fss_status_code_strings_ + #define FSS_STATUS_CODE_failed_to_convert_s "failed to convert" + #define FSS_STATUS_CODE_invalid_number_s "invalid number" + #define FSS_STATUS_CODE_invalid_name_s "invalid name" + #define FSS_STATUS_CODE_invalid_main_s "invalid main" + #define FSS_STATUS_CODE_out_of_range_s "out of range" + #define FSS_STATUS_CODE_unknown_code_s "unknown code" + #define FSS_STATUS_CODE_unknown_name_s "unknown name" + + #define FSS_STATUS_CODE_failed_to_convert_s_length 17 + #define FSS_STATUS_CODE_invalid_number_s_length 14 + #define FSS_STATUS_CODE_invalid_name_s_length 12 + #define FSS_STATUS_CODE_invalid_main_s_length 12 + #define FSS_STATUS_CODE_out_of_range_s_length 12 + #define FSS_STATUS_CODE_unknown_code_s_length 12 + #define FSS_STATUS_CODE_unknown_name_s_length 12 + + extern const f_string_static_t fss_status_code_failed_to_convert_s; + extern const f_string_static_t fss_status_code_invalid_number_s; + extern const f_string_static_t fss_status_code_invalid_name_s; + extern const f_string_static_t fss_status_code_invalid_main_s; + extern const f_string_static_t fss_status_code_out_of_range_s; + extern const f_string_static_t fss_status_code_unknown_code_s; + extern const f_string_static_t fss_status_code_unknown_name_s; +#endif // _di_fss_status_code_strings_ + +/** * The program defines. */ #ifndef _di_fss_status_code_defines_ @@ -152,7 +181,131 @@ extern "C" { } #define fss_status_code_total_parameters_d 16 -#endif // _di_fss_status_code_defines_ +#endif // _di_fss_status_code_parameters_ + +/** + * Flags used to represent flags passed to the main function. + * + * When number mode is not specified, then mode is "string" mode (there is no flag for "string" mode). + * + * fss_status_code_main_flag_*_e: + * - none: No modes in use. + * - error: Check if status is "error". + * - fine: Check if status is "fine". + * - help: Print help. + * - number: Operate in number mode. + * - version: Print version. + * - warning: Check if status is "warning". + */ +#ifndef _di_fss_status_code_main_flag_e_ + enum { + fss_status_code_main_flag_none_e = 0x0, + fss_status_code_main_flag_error_e = 0x1, + fss_status_code_main_flag_fine_e = 0x2, + fss_status_code_main_flag_help_e = 0x4, + fss_status_code_main_flag_number_e = 0x8, + fss_status_code_main_flag_version_e = 0x10, + fss_status_code_main_flag_warning_e = 0x20, + }; +#endif // _di_fss_status_code_main_flag_e_ + +/** + * The status code main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_fss_status_code_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } fss_status_code_setting_t; + + #define fss_status_code_setting_t_initialize \ + { \ + fss_status_code_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_fss_status_code_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_fss_status_code_setting_delete_ + extern f_status_t fss_status_code_setting_delete(fss_status_code_setting_t * const setting); +#endif // _di_fss_status_code_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_fss_status_code_setting_load_ + extern void fss_status_code_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_status_code_setting_t * const setting); +#endif // _di_fss_status_code_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_fss_status_code_setting_unload_ + extern f_status_t fss_status_code_setting_unload(fll_program_data_t * const main, fss_status_code_setting_t * const setting); +#endif // _di_fss_status_code_setting_unload_ #ifdef __cplusplus } // extern "C" diff --git a/level_3/fss_status_code/c/fss_status_code.c b/level_3/fss_status_code/c/fss_status_code.c index c84f07c..3b580e4 100644 --- a/level_3/fss_status_code/c/fss_status_code.c +++ b/level_3/fss_status_code/c/fss_status_code.c @@ -6,165 +6,52 @@ extern "C" { #endif -#ifndef _di_fss_status_code_print_help_ - f_status_t fss_status_code_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, fss_status_code_program_name_long_s, fss_status_code_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, fss_status_code_short_fine_s, fss_status_code_long_fine_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is neither an error nor a warning or print number with neither the error code nor the warning code bits set."); - fll_program_print_help_option(file, context, fss_status_code_short_warning_s, fss_status_code_long_warning_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print F_true or F_false if status code is a warning or print number with warning code bit set."); - fll_program_print_help_option(file, context, fss_status_code_short_error_s, fss_status_code_long_error_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is an error or print number with error code bit set."); - fll_program_print_help_option(file, context, fss_status_code_short_number_s, fss_status_code_long_number_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Convert status code name to number."); - - fll_program_print_help_usage(file, context, fss_status_code_program_name_s, fss_status_code_program_help_parameters_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_fss_status_code_print_help_ - #ifndef _di_fss_status_code_main_ - f_status_t fss_status_code_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { - - f_status_t status = F_none; - - // Load parameters. - status = f_console_parameter_process(arguments, &main->parameters); - if (F_status_is_error(status)) return; - - { - f_array_length_t choice = 0; - f_uint16s_t choices = f_uint16s_t_initialize; - - // Identify and prioritize "color context" parameters. - { - uint16_t choices_array[3] = { fss_status_code_parameter_no_color_e, fss_status_code_parameter_light_e, fss_status_code_parameter_dark_e }; - choices.array = choices_array; - choices.used = 3; - - const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; - - status = fll_program_parameter_process_context(choices, modes, F_true, main); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_context", F_true); - - return; - } - } + void fss_status_code_main(fll_program_data_t * const main, fss_status_code_setting_t * const setting) { - // Identify and prioritize "verbosity" parameters. - { - uint16_t choices_array[5] = { fss_status_code_parameter_verbosity_quiet_e, fss_status_code_parameter_verbosity_error_e, fss_status_code_parameter_verbosity_verbose_e, fss_status_code_parameter_verbosity_debug_e, fss_status_code_parameter_verbosity_normal_e }; - choices.array = choices_array; - choices.used = 5; + if (!main || !setting) { + fss_status_code_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_parameter, "fss_status_code_main", F_true); + fss_status_code_print_line_last(setting, main->error, F_true); - const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + setting->status = F_status_set_error(F_parameter); - status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_verbosity", F_true); - - return; - } - } + return; } - f_string_static_t * const argv = main->parameters.arguments.array; + if (F_status_is_error(setting->status)) return; - status = F_none; + setting->status = F_none; - if (main->parameters.array[fss_status_code_parameter_help_e].result == f_console_result_found_e) { - fss_status_code_print_help(main->output.to, main->context); + if (setting->flag & fss_status_code_main_flag_help_e) { + fss_status_code_print_help(setting, main->message); - return F_none; + return; } - if (main->parameters.array[fss_status_code_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, fss_status_code_program_version_s); + if (setting->flag & fss_status_code_main_flag_version_e) { + fll_program_print_version(main->message, fss_status_code_program_version_s); - return F_none; - } - - if (main->parameters.array[fss_status_code_parameter_error_e].result == f_console_result_found_e) { - if (main->parameters.array[fss_status_code_parameter_warning_e].result == f_console_result_found_e) { - if (main->parameters.array[fss_status_code_parameter_number_e].result == f_console_result_none_e) { - if (main->error.verbosity != f_console_verbosity_quiet_e) { - flockfile(main->error.to.stream); - - fl_print_format("%r%[%QCannot specify the '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context); - fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_status_code_long_error_s, main->error.notable); - fl_print_format("%[' parameter with the '%]", main->error.to.stream, main->error.context, main->error.context); - fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_status_code_long_warning_s, main->error.notable); - fl_print_format("%[' parameter when not also specifying the '%]", main->error.to.stream, main->error.context, main->error.context); - fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, fss_status_code_long_number_s, main->error.notable); - fl_print_format("%[' parameter.%]%r%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s, f_string_eol_s); - - funlockfile(main->error.to.stream); - } - - return F_status_set_error(status); - } - } - - if (main->parameters.array[fss_status_code_parameter_fine_e].result == f_console_result_found_e) { - if (main->error.verbosity != f_console_verbosity_quiet_e) { - fll_program_parameter_long_print_cannot_use_with(main->error, fss_status_code_long_error_s, fss_status_code_long_fine_s); - fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); - } - - return F_status_set_error(status); - } - } - else if (main->parameters.array[fss_status_code_parameter_warning_e].result == f_console_result_found_e && main->parameters.array[fss_status_code_parameter_fine_e].result == f_console_result_found_e) { - if (main->error.verbosity != f_console_verbosity_quiet_e) { - fll_program_parameter_long_print_cannot_use_with(main->error, fss_status_code_long_warning_s, fss_status_code_long_fine_s); - fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); - } - - return F_status_set_error(status); - } - - if (main->parameters.remaining.used == 0 && !(main->pipe & fll_program_data_pipe_input_e)) { - fll_print_format("%[You failed to specify an error code.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s); - - return F_status_set_error(F_parameter); + return; } f_status_t status2 = F_none; - if (main->parameters.array[fss_status_code_parameter_number_e].result == f_console_result_found_e) { + if (setting->flag & fss_status_code_main_flag_number_e) { if (main->pipe & fll_program_data_pipe_input_e) { // @todo call fss_status_code_process_number() here for all main from pipe that is space separated. } if (main->parameters.remaining.used) { - flockfile(main->output.to.stream); + f_file_stream_lock(main->output.to); for (f_array_length_t i = 0; i < main->parameters.remaining.used; ++i) { if (!((++main->signal_check) % fss_status_code_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_status_code_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); - status = F_status_set_error(F_interrupt); + setting->status = F_status_set_error(F_signal); break; } @@ -172,31 +59,31 @@ extern "C" { main->signal_check = 0; } - status2 = fss_status_code_process_number(main, argv[main->parameters.remaining.array[i]]); + status2 = fss_status_code_process_number(main, setting, main->parameters.arguments.array[main->parameters.remaining.array[i]]); - if (F_status_is_error(status2) && status == F_none) { - status = status2; + if (F_status_is_error(status2) && setting->status == F_none) { + setting->status = status2; } } // for - funlockfile(main->output.to.stream); + f_file_stream_unlock(main->output.to); } } - else if (main->parameters.array[fss_status_code_parameter_error_e].result == f_console_result_found_e || main->parameters.array[fss_status_code_parameter_warning_e].result == f_console_result_found_e || main->parameters.array[fss_status_code_parameter_fine_e].result == f_console_result_found_e) { + else if (setting->flag & fss_status_code_main_flag_error_e || setting->flag & fss_status_code_main_flag_warning_e || setting->flag & fss_status_code_main_flag_fine_e) { if (main->pipe & fll_program_data_pipe_input_e) { // @todo call fss_status_code_process_check() here for all main from pipe that is space separated. } if (main->parameters.remaining.used) { - flockfile(main->output.to.stream); + f_file_stream_lock(main->output.to); for (f_array_length_t i = 0; i < main->parameters.remaining.used; ++i) { if (!((++main->signal_check) % fss_status_code_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_status_code_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); - status = F_status_set_error(F_interrupt); + setting->status = F_status_set_error(F_signal); break; } @@ -204,14 +91,14 @@ extern "C" { main->signal_check = 0; } - status2 = fss_status_code_process_check(main, argv[main->parameters.remaining.array[i]]); + status2 = fss_status_code_process_check(main, setting, main->parameters.arguments.array[main->parameters.remaining.array[i]]); - if (F_status_is_error(status2) && status == F_none) { - status = status2; + if (F_status_is_error(status2) && setting->status == F_none) { + setting->status = status2; } } // for - funlockfile(main->output.to.stream); + f_file_stream_unlock(main->output.to); } } else { @@ -220,15 +107,15 @@ extern "C" { } if (main->parameters.remaining.used) { - flockfile(main->output.to.stream); + f_file_stream_lock(main->output.to); for (f_array_length_t i = 0; i < main->parameters.remaining.used; ++i) { if (!((++main->signal_check) % fss_status_code_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - fss_status_code_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); - status = F_status_set_error(F_interrupt); + setting->status = F_status_set_error(F_signal); break; } @@ -236,26 +123,23 @@ extern "C" { main->signal_check = 0; } - status2 = fss_status_code_process_normal(main, argv[main->parameters.remaining.array[i]]); + status2 = fss_status_code_process_normal(main, setting, main->parameters.arguments.array[main->parameters.remaining.array[i]]); - if (F_status_is_error(status2) && status == F_none) { - status = status2; + if (F_status_is_error(status2) && setting->status == F_none) { + setting->status = status2; } } // for - funlockfile(main->output.to.stream); + f_file_stream_unlock(main->output.to); } } - if (F_status_set_fine(status) == F_interrupt) { - if (main->output.verbosity != f_console_verbosity_quiet_e) { - fflush(main->output.to.stream); - - fll_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - } + if (F_status_is_error(setting->status)) { + fss_status_code_print_line_last(setting, main->error, F_true); + } + else if (setting->status != F_interrupt) { + fss_status_code_print_line_last(setting, main->message, F_true); } - - return status; } #endif // _di_fss_status_code_main_ diff --git a/level_3/fss_status_code/c/fss_status_code.h b/level_3/fss_status_code/c/fss_status_code.h index be8a2ce..e3458dd 100644 --- a/level_3/fss_status_code/c/fss_status_code.h +++ b/level_3/fss_status_code/c/fss_status_code.h @@ -1,7 +1,7 @@ /** * FLL - Level 3 * - * Project: FSS + * Project: FSS Status Code * API Version: 0.7 * Licenses: lgpl-2.1-or-later * @@ -44,27 +44,13 @@ // FSS Status Code includes. #include +#include #ifdef __cplusplus extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_fss_status_code_print_help_ - extern f_status_t fss_status_code_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_fss_status_code_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -77,16 +63,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_fss_status_code_main_ - extern f_status_t fss_status_code_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern void fss_status_code_main(fll_program_data_t * const main, fss_status_code_setting_t * const setting); #endif // _di_fss_status_code_main_ #ifdef __cplusplus diff --git a/level_3/fss_status_code/c/main.c b/level_3/fss_status_code/c/main.c index 3cff8f6..1f56485 100644 --- a/level_3/fss_status_code/c/main.c +++ b/level_3/fss_status_code/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + fss_status_code_setting_t setting = fss_status_code_setting_t_initialize; f_console_parameter_t parameters[] = fss_status_code_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = fss_status_code_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = fss_status_code_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + fss_status_code_setting_load(arguments, &data, &setting); + } + + fss_status_code_main(&data, &setting); + + fss_status_code_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status) || status == F_false) return 1; - - return 0; + return (F_status_is_error(setting.status) || setting.status == F_false) ? 1 : 0; } diff --git a/level_3/fss_status_code/c/print.c b/level_3/fss_status_code/c/print.c new file mode 100644 index 0000000..f0d58a2 --- /dev/null +++ b/level_3/fss_status_code/c/print.c @@ -0,0 +1,97 @@ +#include "fss_status_code.h" +#include "private-common.h" +#include "print.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_fss_status_code_print_error_cannot_error_warning_number_ + void fss_status_code_print_error_cannot_error_warning_number(fss_status_code_setting_t * const setting, const fl_print_t print) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + f_file_stream_lock(print.to); + + fl_print_format("%[%QCannot specify the '%]", print.to.stream, print.context, print.prefix, print.context); + fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, fss_status_code_long_error_s, print.notable); + fl_print_format("%[' parameter with the '%]", print.to.stream, print.context, print.context); + fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, fss_status_code_long_warning_s, print.notable); + fl_print_format("%[' parameter when not also specifying the '%]", print.to.stream, print.context, print.context); + fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, fss_status_code_long_number_s, print.notable); + fl_print_format("%[' parameter.%]%r", print.to.stream, print.context, print.context, f_string_eol_s); + + f_file_stream_unlock(print.to); + } +#endif // _di_fss_status_code_print_error_cannot_error_warning_number_ + +#ifndef _di_fss_status_code_print_error_no_fss_status_codes_ + void fss_status_code_print_error_no_fss_status_codes(fss_status_code_setting_t * const setting, const fl_print_t print) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + fll_print_format("%[No status code is specified.%]%r", print.to.stream, print.context, print.context, f_string_eol_s); + } +#endif // _di_fss_status_code_print_error_no_fss_status_codes_ + +#ifndef _di_fss_status_code_print_help_ + f_status_t fss_status_code_print_help(fss_status_code_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, fss_status_code_program_name_long_s, fss_status_code_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, fss_status_code_short_fine_s, fss_status_code_long_fine_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is neither an error nor a warning or print number with neither the error code nor the warning code bits set."); + fll_program_print_help_option(print, fss_status_code_short_warning_s, fss_status_code_long_warning_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print F_true or F_false if status code is a warning or print number with warning code bit set."); + fll_program_print_help_option(print, fss_status_code_short_error_s, fss_status_code_long_error_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is an error or print number with error code bit set."); + fll_program_print_help_option(print, fss_status_code_short_number_s, fss_status_code_long_number_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Convert status code name to number."); + + fll_program_print_help_usage(print, fss_status_code_program_name_s, fss_status_code_program_help_parameters_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_fss_status_code_print_help_ + +#ifndef _di_fss_status_code_print_line_first_ + void fss_status_code_print_line_first(fss_status_code_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_fss_status_code_print_line_first_ + +#ifndef _di_fss_status_code_print_line_last_ + void fss_status_code_print_line_last(fss_status_code_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_fss_status_code_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/fss_status_code/c/print.h b/level_3/fss_status_code/c/print.h new file mode 100644 index 0000000..cca7957 --- /dev/null +++ b/level_3/fss_status_code/c/print.h @@ -0,0 +1,97 @@ +/** + * FLL - Level 3 + * + * Project: FSS Status Code + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _fss_status_code_print_h +#define _fss_status_code_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print an error message when error parameter and warning parameter are specified without number parameter. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + */ +#ifndef _di_fss_status_code_print_error_cannot_error_warning_number_ + extern void fss_status_code_print_error_cannot_error_warning_number(fss_status_code_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_status_code_print_error_cannot_error_warning_number_ + +/** + * Print an error message when no status codes are provided. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + */ +#ifndef _di_fss_status_code_print_error_no_fss_status_codes_ + extern void fss_status_code_print_error_no_fss_status_codes(fss_status_code_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_status_code_print_error_no_fss_status_codes_ + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_fss_status_code_print_help_ + extern f_status_t fss_status_code_print_help(fss_status_code_setting_t * const setting, const fl_print_t print); +#endif // _di_fss_status_code_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_status_code_print_line_first_ + extern void fss_status_code_print_line_first(fss_status_code_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_status_code_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_fss_status_code_print_line_last_ + extern void fss_status_code_print_line_last(fss_status_code_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_fss_status_code_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _fss_status_code_print_h diff --git a/level_3/fss_status_code/c/private-common.c b/level_3/fss_status_code/c/private-common.c index ed96d23..24a88a7 100644 --- a/level_3/fss_status_code/c/private-common.c +++ b/level_3/fss_status_code/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_fss_status_code_print_signal_received_ - void fss_status_code_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_fss_status_code_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_status_code/c/private-common.h b/level_3/fss_status_code/c/private-common.h index 7e8029c..53a416e 100644 --- a/level_3/fss_status_code/c/private-common.h +++ b/level_3/fss_status_code/c/private-common.h @@ -12,26 +12,6 @@ extern "C" { #endif -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_status_code_print_signal_received_ - extern void fss_status_code_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_status_code_print_signal_received_ - -/** - * Print a message about a one parameter not being allowed to be used with another. - * - * @param main - * The main program data. - */ -#ifndef _di_fss_status_code_print_parameter_cannot_be_used_with_ - extern void fss_status_code_print_parameter_cannot_be_used_with(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_fss_status_code_print_parameter_cannot_be_used_with_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/fss_status_code/c/private-fss_status_code.c b/level_3/fss_status_code/c/private-fss_status_code.c index 7ee3d6c..77147b8 100644 --- a/level_3/fss_status_code/c/private-fss_status_code.c +++ b/level_3/fss_status_code/c/private-fss_status_code.c @@ -7,52 +7,30 @@ extern "C" { #endif #ifndef _di_fss_status_code_process_check_ - f_status_t fss_status_code_process_check(fll_program_data_t * const main, const f_string_static_t value) { + f_status_t fss_status_code_process_check(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value) { f_number_unsigned_t number = 0; { - const f_status_t status = fss_status_code_convert_number(main, value, &number); + f_status_t status = fss_status_code_convert_number(main, setting, value, &number); if (F_status_is_error(status)) return status; } - if (main->parameters.array[fss_status_code_parameter_error_e].result == f_console_result_found_e) { - if (F_status_is_error(number)) { - f_print_dynamic_raw(f_status_true_s, main->output.to.stream); - } - else { - f_print_dynamic_raw(f_status_false_s, main->output.to.stream); - } - - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + if ((setting->flag & fss_status_code_main_flag_error_e) && F_status_is_error(number) || (setting->flag & fss_status_code_main_flag_warning_e) && F_status_is_warning(number) || (setting->flag & fss_status_code_main_flag_fine_e) && F_status_is_fine(number)) { + f_print_dynamic_raw(f_status_true_s, main->output.to.stream); } - else if (main->parameters.array[fss_status_code_parameter_warning_e].result == f_console_result_found_e) { - if (F_status_is_warning(number)) { - f_print_dynamic_raw(f_status_true_s, main->output.to.stream); - } - else { - f_print_dynamic_raw(f_status_false_s, main->output.to.stream); - } - - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + else { + f_print_dynamic_raw(f_status_false_s, main->output.to.stream); } - else if (main->parameters.array[fss_status_code_parameter_fine_e].result == f_console_result_found_e) { - if (F_status_is_fine(number)) { - f_print_dynamic_raw(f_status_true_s, main->output.to.stream); - } - else { - f_print_dynamic_raw(f_status_false_s, main->output.to.stream); - } - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - } + f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); return F_none; } #endif // _di_fss_status_code_process_check_ #ifndef _di_fss_status_code_process_number_ - f_status_t fss_status_code_process_number(fll_program_data_t * const main, const f_string_static_t value) { + f_status_t fss_status_code_process_number(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value) { f_status_t status = F_none; @@ -62,13 +40,13 @@ extern "C" { status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, value, &number); if (status == F_none) { - fl_print_format("%[invalid name%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_invalid_name_s, main->context.set.error, f_string_eol_s); return F_status_set_error(F_parameter); } if (status == F_data_not || F_status_set_fine(status) == F_parameter) { - fl_print_format("%[invalid main%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_invalid_main_s, main->context.set.error, f_string_eol_s); return status; } @@ -85,10 +63,10 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown name%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_unknown_name_s, main->context.set.error, f_string_eol_s); } else { - fl_print_format("%[failed to convert%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_failed_to_convert_s, main->context.set.error, f_string_eol_s); } return status; @@ -96,16 +74,16 @@ extern "C" { } if (status == F_data) { - fl_print_format("%[unknown code%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_unknown_code_s, main->context.set.error, f_string_eol_s); return F_none; } - if (main->parameters.array[fss_status_code_parameter_error_e].result == f_console_result_found_e) { + if (setting->flag & fss_status_code_main_flag_error_e) { code = F_status_set_error(code); } - if (main->parameters.array[fss_status_code_parameter_warning_e].result == f_console_result_found_e) { + if (setting->flag & fss_status_code_main_flag_warning_e) { code = F_status_set_warning(code); } @@ -116,11 +94,11 @@ extern "C" { #endif // _di_fss_status_code_process_number_ #ifndef _di_fss_status_code_process_normal_ - f_status_t fss_status_code_process_normal(fll_program_data_t * const main, const f_string_static_t value) { + f_status_t fss_status_code_process_normal(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value) { f_number_unsigned_t number = 0; - f_status_t status = fss_status_code_convert_number(main, value, &number); + f_status_t status = fss_status_code_convert_number(main, setting, value, &number); if (F_status_is_error(status)) return status; f_string_static_t name = f_string_static_t_initialize; @@ -129,10 +107,10 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown code%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_unknown_code_s, main->context.set.error, f_string_eol_s); } else { - fl_print_format("%[failed to convert%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_failed_to_convert_s, main->context.set.error, f_string_eol_s); } return status; @@ -145,22 +123,22 @@ extern "C" { #endif // _di_fss_status_code_process_normal_ #ifndef _di_fss_status_code_convert_number_ - f_status_t fss_status_code_convert_number(fll_program_data_t * const main, const f_string_static_t value, f_number_unsigned_t *number) { + f_status_t fss_status_code_convert_number(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value, f_number_unsigned_t *number) { - f_status_t status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, value, number); + const f_status_t status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, value, number); if (*number > F_status_size_max_with_bits_d) { - fl_print_format("%[out of range%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_out_of_range_s, main->context.set.error, f_string_eol_s); return F_status_set_error(F_number_overflow); } if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_number_negative) { - fl_print_format("%[out of range%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_out_of_range_s, main->context.set.error, f_string_eol_s); } else { - fl_print_format("%[invalid number%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, fss_status_code_invalid_number_s, main->context.set.error, f_string_eol_s); } return status; diff --git a/level_3/fss_status_code/c/private-fss_status_code.h b/level_3/fss_status_code/c/private-fss_status_code.h index 182c93d..56a600b 100644 --- a/level_3/fss_status_code/c/private-fss_status_code.h +++ b/level_3/fss_status_code/c/private-fss_status_code.h @@ -1,7 +1,7 @@ /** * FLL - Level 3 * - * Project: FSS + * Project: FSS Status Code * API Version: 0.7 * Licenses: lgpl-2.1-or-later */ @@ -29,12 +29,12 @@ extern "C" { * F_number_overflow (with error bit) on integer overflow. * F_complete_not_utf (with error bit) if an incomplete UTF-8 fragment is found. * - * Errors (with error bit) from: fss_status_code_convert_number(). + * Errors (with error bit) from: fss_fss_status_code_convert_number(). * - * @see fss_status_code_convert_number() + * @see fss_fss_status_code_convert_number() */ #ifndef _di_fss_status_code_process_check_ - extern f_status_t fss_status_code_process_check(fll_program_data_t * const main, const f_string_static_t value) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_process_check(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_process_check_ /** @@ -56,7 +56,7 @@ extern "C" { * @see fll_fss_status_string_from() */ #ifndef _di_fss_status_code_process_number_ - extern f_status_t fss_status_code_process_number(fll_program_data_t * const main, const f_string_static_t value) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_process_number(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_process_number_ /** @@ -77,13 +77,13 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * * Errors (with error bit) from: fll_fss_status_string_from(). - * Errors (with error bit) from: fss_status_code_convert_number(). + * Errors (with error bit) from: fss_fss_status_code_convert_number(). * * @see fll_fss_status_string_from() - * @see fss_status_code_convert_number() + * @see fss_fss_status_code_convert_number() */ #ifndef _di_fss_status_code_process_normal_ - extern f_status_t fss_status_code_process_normal(fll_program_data_t * const main, const f_string_static_t value) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_process_normal(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_process_normal_ /** @@ -111,7 +111,7 @@ extern "C" { * @see fl_console_parameter_to_number_unsigned() */ #ifndef _di_fss_status_code_convert_number_ - extern f_status_t fss_status_code_convert_number(fll_program_data_t * const main, const f_string_static_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t fss_status_code_convert_number(fll_program_data_t * const main, fss_status_code_setting_t * const setting, const f_string_static_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_fss_status_code_convert_number_ #ifdef __cplusplus diff --git a/level_3/fss_status_code/data/build/settings b/level_3/fss_status_code/data/build/settings index 703e580..f223e89 100644 --- a/level_3/fss_status_code/data/build/settings +++ b/level_3/fss_status_code/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_file -lfll_fss -lfll_fss_status_str build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library fss_status_code.c common.c private-common.c private-fss_status_code.c +build_sources_library fss_status_code.c common.c print.c private-common.c private-fss_status_code.c build_sources_program main.c -build_sources_headers fss_status_code.h common.h +build_sources_headers fss_status_code.h common.h print.h build_script yes build_shared yes diff --git a/level_3/iki_read/c/common.c b/level_3/iki_read/c/common.c index 00af882..a0ccf60 100644 --- a/level_3/iki_read/c/common.c +++ b/level_3/iki_read/c/common.c @@ -47,6 +47,358 @@ extern "C" { const f_string_static_t iki_read_substitution_with_s = macro_f_string_static_t_initialize(IKI_READ_substitution_with_s, 0, IKI_READ_substitution_with_s_length); #endif // _di_iki_read_substitution_t_ +#ifndef _di_iki_read_setting_delete_ + f_status_t iki_read_setting_delete(iki_read_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_iki_read_setting_delete_ + +#ifndef _di_iki_read_setting_load_ + void iki_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, iki_read_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { iki_read_parameter_no_color_e, iki_read_parameter_light_e, iki_read_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + iki_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[iki_read_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[iki_read_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { iki_read_parameter_verbosity_quiet_e, iki_read_parameter_verbosity_error_e, iki_read_parameter_verbosity_verbose_e, iki_read_parameter_verbosity_debug_e, iki_read_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + iki_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[iki_read_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= iki_read_main_flag_help_e; + + return; + } + + if (main->parameters.array[iki_read_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= iki_read_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { iki_read_parameter_from_bytesequence_e, iki_read_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + iki_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == iki_read_parameter_from_bytesequence_e) { + if (setting->mode & iki_read_mode_from_codepoint_e) { + setting->mode -= iki_read_mode_from_codepoint_e; + } + + setting->mode |= iki_read_mode_from_bytesequence_e; + } + else if (choices.array[choice] == iki_read_parameter_from_codepoint_e) { + if (setting->mode & iki_read_mode_from_bytesequence_e) { + setting->mode -= iki_read_mode_from_bytesequence_e; + } + + setting->mode |= iki_read_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { iki_read_parameter_to_bytesequence_e, iki_read_parameter_to_codepoint_e, iki_read_parameter_to_combining_e, iki_read_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + iki_read_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == iki_read_parameter_to_bytesequence_e) { + if (setting->mode & iki_read_mode_to_codepoint_e) { + setting->mode -= iki_read_mode_to_codepoint_e; + } + + if (setting->mode & iki_read_mode_to_combining_e) { + setting->mode -= iki_read_mode_to_combining_e; + } + + if (setting->mode & iki_read_mode_to_width_e) { + setting->mode -= iki_read_mode_to_width_e; + } + + setting->mode |= iki_read_mode_to_bytesequence_e; + } + else if (choices.array[choice] == iki_read_parameter_to_codepoint_e) { + if (setting->mode & iki_read_mode_to_bytesequence_e) { + setting->mode -= iki_read_mode_to_bytesequence_e; + } + + if (setting->mode & iki_read_mode_to_combining_e) { + setting->mode -= iki_read_mode_to_combining_e; + } + + if (setting->mode & iki_read_mode_to_width_e) { + setting->mode -= iki_read_mode_to_width_e; + } + + setting->mode |= iki_read_mode_to_codepoint_e; + } + else if (choices.array[choice] == iki_read_parameter_to_combining_e) { + if (setting->mode & iki_read_mode_to_bytesequence_e) { + setting->mode -= iki_read_mode_to_bytesequence_e; + } + + if (setting->mode & iki_read_mode_to_codepoint_e) { + setting->mode -= iki_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[iki_read_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= iki_read_mode_to_width_e; + } + + setting->mode |= iki_read_mode_to_combining_e; + } + else if (choices.array[choice] == iki_read_parameter_to_width_e) { + if (setting->mode & iki_read_mode_to_bytesequence_e) { + setting->mode -= iki_read_mode_to_bytesequence_e; + } + + if (setting->mode & iki_read_mode_to_codepoint_e) { + setting->mode -= iki_read_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[iki_read_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= iki_read_mode_to_combining_e; + } + + setting->mode |= iki_read_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[iki_read_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[iki_read_parameter_to_file_e].values.used > 1) { + iki_read_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[iki_read_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[iki_read_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[iki_read_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[iki_read_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= iki_read_main_flag_file_to_e; + } + else { + iki_read_print_error_parameter_file_name_empty(main, setting, main->parameters.array[iki_read_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[iki_read_parameter_to_file_e].result == f_console_result_found_e) { + iki_read_print_error_no_value(main, setting, iki_read_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & iki_read_main_flag_file_to_e) { + setting->flag -= iki_read_main_flag_file_to_e; + } + } + + if (main->parameters.array[iki_read_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[iki_read_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[iki_read_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[iki_read_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + iki_read_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + iki_read_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= iki_read_main_flag_file_from_e; + } + else if (main->parameters.array[iki_read_parameter_from_file_e].result == f_console_result_found_e) { + iki_read_print_error_no_value(main, setting, iki_read_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & iki_read_main_flag_file_from_e) { + setting->flag -= iki_read_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[iki_read_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + iki_read_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & iki_read_mode_to_bytesequence_e)) { + if (main->parameters.array[iki_read_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[iki_read_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = iki_read_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[iki_read_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= iki_read_main_flag_header_e; + } + + if (main->parameters.array[iki_read_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= iki_read_main_flag_separate_e; + } + + if (main->parameters.array[iki_read_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= iki_read_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_iki_read_setting_load_ + +#ifndef _di_iki_read_setting_unload_ + f_status_t iki_read_setting_unload(fll_program_data_t * const main, iki_read_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + iki_read_setting_delete(setting); + + return F_none; + } +#endif // _di_iki_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_read/c/common.h b/level_3/iki_read/c/common.h index 945aa8b..70f25e0 100644 --- a/level_3/iki_read/c/common.h +++ b/level_3/iki_read/c/common.h @@ -264,6 +264,132 @@ extern "C" { #define macro_iki_read_substitutions_t_adjust(status, replacements, length) macro_f_memory_structure_adjust(status, replacements, iki_read_substitution_t, length) #endif // _di_iki_read_substitutions_t_ +/** + * Flags used to represent flags passed to the main function. + * + * iki_read_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_iki_read_main_flag_e_ + enum { + iki_read_main_flag_none_e = 0x0, + iki_read_main_flag_file_from_e = 0x1, + iki_read_main_flag_file_to_e = 0x2, + iki_read_main_flag_header_e = 0x4, + iki_read_main_flag_help_e = 0x8, + iki_read_main_flag_separate_e = 0x10, + iki_read_main_flag_strip_invalid_e = 0x20, + iki_read_main_flag_verify_e = 0x40, + iki_read_main_flag_version_e = 0x80, + }; +#endif // _di_iki_read_main_flag_e_ + +/** + * The iki read main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_iki_read_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } iki_read_setting_t; + + #define iki_read_setting_t_initialize \ + { \ + iki_read_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_iki_read_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_iki_read_setting_delete_ + extern f_status_t iki_read_setting_delete(iki_read_setting_t * const setting); +#endif // _di_iki_read_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_iki_read_setting_load_ + extern void iki_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, iki_read_setting_t * const setting); +#endif // _di_iki_read_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_iki_read_setting_unload_ + extern f_status_t iki_read_setting_unload(fll_program_data_t * const main, iki_read_setting_t * const setting); +#endif // _di_iki_read_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_read/c/iki_read.c b/level_3/iki_read/c/iki_read.c index 927eea7..3b03fb6 100644 --- a/level_3/iki_read/c/iki_read.c +++ b/level_3/iki_read/c/iki_read.c @@ -6,101 +6,8 @@ extern "C" { #endif -#ifndef _di_iki_read_print_help_ - f_status_t iki_read_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, iki_read_program_name_long_s, iki_read_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, iki_read_short_at_s, iki_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select variable at this numeric index."); - fll_program_print_help_option(file, context, iki_read_short_line_s, iki_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the variables at the given line within the file."); - fll_program_print_help_option(file, context, iki_read_short_name_s, iki_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select variables with this name."); - fll_program_print_help_option(file, context, iki_read_short_whole_s, iki_read_long_whole_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print all of the data instead of just the IKI variable data."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, iki_read_short_content_s, iki_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the variable value (aka: content) (default)"); - fll_program_print_help_option(file, context, iki_read_short_literal_s, iki_read_long_literal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the entire variable (aka: object, content, and syntax)."); - fll_program_print_help_option(file, context, iki_read_short_object_s, iki_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the variable name (aka: object)."); - fll_program_print_help_option(file, context, iki_read_short_total_s, iki_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of variables."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, iki_read_short_replace_s, iki_read_long_replace_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Simple substitution, replacing the variable for the given name with the given string."); - fll_program_print_help_option(file, context, iki_read_short_substitute_s, iki_read_long_substitute_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Substitute the variable for the given name and matching content value with the given string."); - fll_program_print_help_option(file, context, iki_read_short_wrap_s, iki_read_long_wrap_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Prepend and append strings for the given name."); - - fll_program_print_help_usage(file, context, iki_read_program_name_s, fll_program_parameter_filenames_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - fl_print_format(" This program will find and print variables, vocabularies, or content following the IKI standard, without focusing on any particular vocabulary specification.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] option requires 2 additional parameters:", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable); - fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, context.set.notable); - fl_print_format(" %[<%]%r%[>%].%r", file.stream, context.set.notable, context.set.notable, iki_read_substitution_with_s, context.set.notable, context.set.notable, f_string_eol_s); - - fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be substituted.%r", file.stream, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%]: The new string to use as the substitute.%r%r", file.stream, context.set.notable, iki_read_substitution_with_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The vocabulary is case-sensitive and must exactly match.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] option requires 3 additional parameters:", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); - fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, context.set.notable); - fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_replace_s, context.set.notable, context.set.notable); - fl_print_format(" %[<%]%r%[>%].%r", file.stream, context.set.notable, context.set.notable, iki_read_substitution_with_s, context.set.notable, context.set.notable, f_string_eol_s); - - fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be substituted.%r", file.stream, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%]: The content matching this exact string will be substituted.%r", file.stream, context.set.notable, iki_read_substitution_replace_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%]: The new string to use as the substitute.%r%r", file.stream, context.set.notable, iki_read_substitution_with_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The vocabulary and replacement are case-sensitive and must exactly match.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%] option requires 3 additional parameters:", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_wrap_s, context.set.notable); - fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, context.set.notable); - fl_print_format(" %[<%]%r%[>%]", file.stream, context.set.notable, context.set.notable, iki_read_substitution_before_s, context.set.notable, context.set.notable); - fl_print_format(" %[<%]%r%[>%].%r", file.stream, context.set.notable, context.set.notable, iki_read_substitution_after_s, context.set.notable, context.set.notable, f_string_eol_s); - - fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be wrapped.%r", file.stream, context.set.notable, iki_read_substitution_vocabulary_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%]: The string to prepend.%r", file.stream, context.set.notable, iki_read_substitution_before_s, context.set.notable, f_string_eol_s); - fl_print_format(" %[%r%]: The string to append.%r%r", file.stream, context.set.notable, iki_read_substitution_after_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The vocabulary is case-sensitive and must exactly match.%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The difference between %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable); - fl_print_format(" and %[%r%r%] is that the", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); - fl_print_format(" %[%r%r%] option substitutes all matching vocabulary names and the", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable); - fl_print_format(" %[%r%r%] option substitutes all matching vocabulary names that must also have the given matching content.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable); - fl_print_format(" option takes priority over the %[%r%r%] option when matching the same variable.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The %[%r%r%]", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_wrap_s, context.set.notable); - fl_print_format(" option is ignored when the %[%r%r%] option is matching the same variable.%r%r", file.stream, context.set.notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, context.set.notable, f_string_eol_s, f_string_eol_s); - - fl_print_format(" The default behavior is to only display content portion of the IKI variable.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_iki_read_print_help_ - #ifndef _di_iki_read_main_ - f_status_t iki_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t iki_read_main(fll_program_data_t * const main, iki_read_setting_t * const setting) { f_status_t status = F_none; @@ -154,7 +61,7 @@ extern "C" { status = F_none; if (main->parameters.array[iki_read_parameter_help_e].result == f_console_result_found_e) { - iki_read_print_help(main->output.to, main->context); + iki_read_print_help(setting, main->message); iki_read_data_delete(&data); @@ -162,7 +69,7 @@ extern "C" { } if (main->parameters.array[iki_read_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, iki_read_program_version_s); + fll_program_print_version(main->message, iki_read_program_version_s); iki_read_data_delete(&data); @@ -401,7 +308,7 @@ extern "C" { if (!((++main->signal_check) % iki_read_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - iki_read_print_signal_received(&data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); @@ -469,7 +376,7 @@ extern "C" { // The signal check is always performed on each pass. if (size_file > iki_read_block_max && fll_program_standard_signal_received(main)) { - iki_read_print_signal_received(&data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/iki_read/c/iki_read.h b/level_3/iki_read/c/iki_read.h index 79d0f5f..d26c134 100644 --- a/level_3/iki_read/c/iki_read.h +++ b/level_3/iki_read/c/iki_read.h @@ -58,21 +58,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_iki_read_print_help_ - extern f_status_t iki_read_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_iki_read_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -85,16 +70,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_iki_read_main_ - extern f_status_t iki_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t iki_read_main(fll_program_data_t * const main, iki_read_setting_t * const setting); #endif // _di_iki_read_main_ #ifdef __cplusplus diff --git a/level_3/iki_read/c/main.c b/level_3/iki_read/c/main.c index 56ed1be..87d88e4 100644 --- a/level_3/iki_read/c/main.c +++ b/level_3/iki_read/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + iki_read_setting_t setting = iki_read_setting_t_initialize; f_console_parameter_t parameters[] = iki_read_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = iki_read_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = iki_read_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + iki_read_setting_load(arguments, &data, &setting); + } + + iki_read_main(&data, &setting); + + iki_read_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/iki_read/c/print.c b/level_3/iki_read/c/print.c new file mode 100644 index 0000000..e901ed1 --- /dev/null +++ b/level_3/iki_read/c/print.c @@ -0,0 +1,130 @@ +#include "iki_read.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_iki_read_print_help_ + f_status_t iki_read_print_help(iki_read_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, iki_read_program_name_long_s, iki_read_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, iki_read_short_at_s, iki_read_long_at_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select variable at this numeric index."); + fll_program_print_help_option(print, iki_read_short_line_s, iki_read_long_line_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print only the variables at the given line within the file."); + fll_program_print_help_option(print, iki_read_short_name_s, iki_read_long_name_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Select variables with this name."); + fll_program_print_help_option(print, iki_read_short_whole_s, iki_read_long_whole_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print all of the data instead of just the IKI variable data."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, iki_read_short_content_s, iki_read_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the variable value (aka: content) (default)"); + fll_program_print_help_option(print, iki_read_short_literal_s, iki_read_long_literal_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print the entire variable (aka: object, content, and syntax)."); + fll_program_print_help_option(print, iki_read_short_object_s, iki_read_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the variable name (aka: object)."); + fll_program_print_help_option(print, iki_read_short_total_s, iki_read_long_total_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print the total number of variables."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, iki_read_short_replace_s, iki_read_long_replace_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Simple substitution, replacing the variable for the given name with the given string."); + fll_program_print_help_option(print, iki_read_short_substitute_s, iki_read_long_substitute_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Substitute the variable for the given name and matching content value with the given string."); + fll_program_print_help_option(print, iki_read_short_wrap_s, iki_read_long_wrap_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Prepend and append strings for the given name."); + + fll_program_print_help_usage(print, iki_read_program_name_s, fll_program_parameter_filenames_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + fl_print_format(" This program will find and print variables, vocabularies, or content following the IKI standard, without focusing on any particular vocabulary specification.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] option requires 2 additional parameters:", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, print.set->notable); + fl_print_format(" %[<%]%r%[>%]", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_vocabulary_s, print.set->notable, print.set->notable); + fl_print_format(" %[<%]%r%[>%].%r", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_with_s, print.set->notable, print.set->notable, f_string_eol_s); + + fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be substituted.%r", print.to.stream, print.set->notable, iki_read_substitution_vocabulary_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%]: The new string to use as the substitute.%r%r", print.to.stream, print.set->notable, iki_read_substitution_with_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The vocabulary is case-sensitive and must exactly match.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] option requires 3 additional parameters:", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, print.set->notable); + fl_print_format(" %[<%]%r%[>%]", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_vocabulary_s, print.set->notable, print.set->notable); + fl_print_format(" %[<%]%r%[>%]", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_replace_s, print.set->notable, print.set->notable); + fl_print_format(" %[<%]%r%[>%].%r", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_with_s, print.set->notable, print.set->notable, f_string_eol_s); + + fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be substituted.%r", print.to.stream, print.set->notable, iki_read_substitution_vocabulary_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%]: The content matching this exact string will be substituted.%r", print.to.stream, print.set->notable, iki_read_substitution_replace_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%]: The new string to use as the substitute.%r%r", print.to.stream, print.set->notable, iki_read_substitution_with_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The vocabulary and replacement are case-sensitive and must exactly match.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%] option requires 3 additional parameters:", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_wrap_s, print.set->notable); + fl_print_format(" %[<%]%r%[>%]", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_vocabulary_s, print.set->notable, print.set->notable); + fl_print_format(" %[<%]%r%[>%]", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_before_s, print.set->notable, print.set->notable); + fl_print_format(" %[<%]%r%[>%].%r", print.to.stream, print.set->notable, print.set->notable, iki_read_substitution_after_s, print.set->notable, print.set->notable, f_string_eol_s); + + fl_print_format(" %[%r%]: The name of the vocabulary whose content is to be wrapped.%r", print.to.stream, print.set->notable, iki_read_substitution_vocabulary_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%]: The string to prepend.%r", print.to.stream, print.set->notable, iki_read_substitution_before_s, print.set->notable, f_string_eol_s); + fl_print_format(" %[%r%]: The string to append.%r%r", print.to.stream, print.set->notable, iki_read_substitution_after_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The vocabulary is case-sensitive and must exactly match.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The difference between %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, print.set->notable); + fl_print_format(" and %[%r%r%] is that the", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, print.set->notable); + fl_print_format(" %[%r%r%] option substitutes all matching vocabulary names and the", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, print.set->notable); + fl_print_format(" %[%r%r%] option substitutes all matching vocabulary names that must also have the given matching content.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, print.set->notable); + fl_print_format(" option takes priority over the %[%r%r%] option when matching the same variable.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_replace_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The %[%r%r%]", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_wrap_s, print.set->notable); + fl_print_format(" option is ignored when the %[%r%r%] option is matching the same variable.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, iki_read_long_substitute_s, print.set->notable, f_string_eol_s, f_string_eol_s); + + fl_print_format(" The default behavior is to only display content portion of the IKI variable.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_iki_read_print_help_ + +#ifndef _di_iki_read_print_line_first_ + void iki_read_print_line_first(iki_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_iki_read_print_line_first_ + +#ifndef _di_iki_read_print_line_last_ + void iki_read_print_line_last(iki_read_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & iki_read_main_flag_verify_e) return; + if ((setting->flag & iki_read_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_iki_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/iki_read/c/print.h b/level_3/iki_read/c/print.h new file mode 100644 index 0000000..9afe978 --- /dev/null +++ b/level_3/iki_read/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _iki_read_print_h +#define _iki_read_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_iki_read_print_help_ + extern f_status_t iki_read_print_help(iki_read_setting_t * const setting, const fl_print_t print); +#endif // _di_iki_read_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_iki_read_print_line_first_ + extern void iki_read_print_line_first(iki_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_iki_read_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_iki_read_print_line_last_ + extern void iki_read_print_line_last(iki_read_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_iki_read_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _iki_read_print_h diff --git a/level_3/iki_read/c/private-common.c b/level_3/iki_read/c/private-common.c index 3173b73..6d208ab 100644 --- a/level_3/iki_read/c/private-common.c +++ b/level_3/iki_read/c/private-common.c @@ -6,7 +6,7 @@ extern "C" { #endif #ifndef _di_iki_read_data_delete_ - f_status_t iki_read_data_delete(iki_read_data_t * const data) { + f_status_t iki_read_data_delete(fll_program_data_t * const main, status_code_setting_t * const setting, iki_read_data_t * const data) { f_string_dynamic_resize(0, &data->buffer); @@ -14,24 +14,6 @@ extern "C" { } #endif // _di_iki_read_data_delete_ -#ifndef _di_iki_read_print_signal_received_ - void iki_read_print_signal_received(iki_read_data_t * const data) { - - if (data->main->warning.verbosity != f_console_verbosity_verbose_e && data->main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(data->main->warning.to.stream); - - flockfile(data->main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", data->main->warning.to.stream, data->main->context.set.reset, f_string_eol_s, f_string_eol_s, data->main->context.set.warning, data->main->context.set.warning); - fl_print_format("%[%i%]", data->main->warning.to.stream, data->main->context.set.notable, data->main->signal_received, data->main->context.set.notable); - fl_print_format("%[.%]%r", data->main->warning.to.stream, data->main->context.set.warning, data->main->context.set.warning, f_string_eol_s); - - funlockfile(data->main->warning.to.stream); - } -#endif // _di_iki_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_read/c/private-common.h b/level_3/iki_read/c/private-common.h index 471afcc..3039b9a 100644 --- a/level_3/iki_read/c/private-common.h +++ b/level_3/iki_read/c/private-common.h @@ -77,19 +77,9 @@ extern "C" { * F_none on success. */ #ifndef _di_iki_read_data_delete_ - extern f_status_t iki_read_data_delete(iki_read_data_t * const data) F_attribute_visibility_internal_d; + extern f_status_t iki_read_data_delete(fll_program_data_t * const main, status_code_setting_t * const setting, iki_read_data_t * const data) F_attribute_visibility_internal_d; #endif // _di_iki_read_data_delete_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param data - * The program data. - */ -#ifndef _di_iki_read_print_signal_received_ - extern void iki_read_print_signal_received(iki_read_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_iki_read_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_read/c/private-print.c b/level_3/iki_read/c/private-print.c index 1848ff6..c4f81a2 100644 --- a/level_3/iki_read/c/private-print.c +++ b/level_3/iki_read/c/private-print.c @@ -7,7 +7,7 @@ extern "C" { #endif #ifndef _di_iki_read_substitutions_print_ - void iki_read_substitutions_print(iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitution_t replacement, const iki_read_substitution_t wraps, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) { + void iki_read_substitutions_print(fll_program_data_t * const main, status_code_setting_t * const setting, iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitution_t replacement, const iki_read_substitution_t wraps, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) { uint8_t matched = F_false; f_array_length_t at = 0; diff --git a/level_3/iki_read/c/private-print.h b/level_3/iki_read/c/private-print.h index 4c8ec6a..99332ff 100644 --- a/level_3/iki_read/c/private-print.h +++ b/level_3/iki_read/c/private-print.h @@ -35,7 +35,7 @@ extern "C" { * Set to FALSE to print the entire variable when printing substituted text. */ #ifndef _di_iki_read_substitutions_print_ - extern void iki_read_substitutions_print(iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitution_t replacement, const iki_read_substitution_t wraps, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) F_attribute_visibility_internal_d; + extern void iki_read_substitutions_print(fll_program_data_t * const main, status_code_setting_t * const setting, iki_read_data_t * const data, const f_iki_data_t iki_data, const f_string_ranges_t ranges, const iki_read_substitution_t replacement, const iki_read_substitution_t wraps, const iki_read_substitutions_t substitutions, const f_array_length_t index, const bool content_only) F_attribute_visibility_internal_d; #endif // _di_iki_read_substitutions_print_ #ifdef __cplusplus diff --git a/level_3/iki_read/c/private-read.c b/level_3/iki_read/c/private-read.c index 79b2b32..3f91b7f 100644 --- a/level_3/iki_read/c/private-read.c +++ b/level_3/iki_read/c/private-read.c @@ -8,7 +8,7 @@ extern "C" { #endif #ifndef _di_iki_read_process_at_ - f_status_t iki_read_process_at(iki_read_data_t * const data, f_string_range_t *range) { + f_status_t iki_read_process_at(fll_program_data_t * const main, status_code_setting_t * const setting, iki_read_data_t * const data, f_string_range_t *range) { if (data->main->parameters.array[iki_read_parameter_line_e].result != f_console_result_additional_e) { return F_false; @@ -539,7 +539,7 @@ extern "C" { if (!((++data->main->signal_check) % iki_read_signal_check_d)) { if (fll_program_standard_signal_received(data->main)) { - iki_read_print_signal_received(data); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); f_string_dynamic_resize(0, &name); diff --git a/level_3/iki_read/c/private-read.h b/level_3/iki_read/c/private-read.h index 84a2dd0..f41b1df 100644 --- a/level_3/iki_read/c/private-read.h +++ b/level_3/iki_read/c/private-read.h @@ -31,7 +31,7 @@ extern "C" { * Status codes (with error bit) are returned on any problem. */ #ifndef _di_iki_read_process_at_ - extern f_status_t iki_read_process_at(iki_read_data_t * const data, f_string_range_t *range) F_attribute_visibility_internal_d; + extern f_status_t iki_read_process_at(fll_program_data_t * const main, status_code_setting_t * const setting, iki_read_data_t * const data, f_string_range_t *range) F_attribute_visibility_internal_d; #endif // _di_iki_read_process_at_ /** diff --git a/level_3/iki_read/data/build/settings b/level_3/iki_read/data/build/settings index f3e93fd..b734186 100644 --- a/level_3/iki_read/data/build/settings +++ b/level_3/iki_read/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_print -lfll_program -lfl_conversion build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library iki_read.c common.c private-common.c private-print.c private-read.c +build_sources_library iki_read.c common.c print.c private-common.c private-print.c private-read.c build_sources_program main.c -build_sources_headers iki_read.h common.h +build_sources_headers iki_read.h common.h print.h build_script yes build_shared yes diff --git a/level_3/iki_write/c/common.c b/level_3/iki_write/c/common.c index 95d8b88..993dc44 100644 --- a/level_3/iki_write/c/common.c +++ b/level_3/iki_write/c/common.c @@ -27,6 +27,358 @@ extern "C" { const f_string_static_t iki_write_long_single_s = macro_f_string_static_t_initialize(IKI_WRITE_long_single_s, 0, IKI_WRITE_long_single_s_length); #endif // _di_iki_write_parameters_ +#ifndef _di_iki_write_setting_delete_ + f_status_t iki_write_setting_delete(iki_write_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_iki_write_setting_delete_ + +#ifndef _di_iki_write_setting_load_ + void iki_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, iki_write_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { iki_write_parameter_no_color_e, iki_write_parameter_light_e, iki_write_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + iki_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + + return; + } + } + + if (main->parameters.array[iki_write_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[iki_write_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { iki_write_parameter_verbosity_quiet_e, iki_write_parameter_verbosity_error_e, iki_write_parameter_verbosity_verbose_e, iki_write_parameter_verbosity_debug_e, iki_write_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + iki_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + + return; + } + } + + if (main->parameters.array[iki_write_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= iki_write_main_flag_help_e; + + return; + } + + if (main->parameters.array[iki_write_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= iki_write_main_flag_version_e; + + return; + } + + // Identify and prioritize "from" mode parameters. + { + uint16_t choices_array[2] = { iki_write_parameter_from_bytesequence_e, iki_write_parameter_from_codepoint_e }; + choices.array = choices_array; + choices.used = 2; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + iki_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == iki_write_parameter_from_bytesequence_e) { + if (setting->mode & iki_write_mode_from_codepoint_e) { + setting->mode -= iki_write_mode_from_codepoint_e; + } + + setting->mode |= iki_write_mode_from_bytesequence_e; + } + else if (choices.array[choice] == iki_write_parameter_from_codepoint_e) { + if (setting->mode & iki_write_mode_from_bytesequence_e) { + setting->mode -= iki_write_mode_from_bytesequence_e; + } + + setting->mode |= iki_write_mode_from_codepoint_e; + } + } + + // Identify and prioritize "to" mode parameters. + { + uint16_t choices_array[4] = { iki_write_parameter_to_bytesequence_e, iki_write_parameter_to_codepoint_e, iki_write_parameter_to_combining_e, iki_write_parameter_to_width_e }; + choices.array = choices_array; + choices.used = 4; + choice = 1; + + setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); + + if (F_status_is_error(setting->status)) { + iki_write_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + + return; + } + + if (choices.array[choice] == iki_write_parameter_to_bytesequence_e) { + if (setting->mode & iki_write_mode_to_codepoint_e) { + setting->mode -= iki_write_mode_to_codepoint_e; + } + + if (setting->mode & iki_write_mode_to_combining_e) { + setting->mode -= iki_write_mode_to_combining_e; + } + + if (setting->mode & iki_write_mode_to_width_e) { + setting->mode -= iki_write_mode_to_width_e; + } + + setting->mode |= iki_write_mode_to_bytesequence_e; + } + else if (choices.array[choice] == iki_write_parameter_to_codepoint_e) { + if (setting->mode & iki_write_mode_to_bytesequence_e) { + setting->mode -= iki_write_mode_to_bytesequence_e; + } + + if (setting->mode & iki_write_mode_to_combining_e) { + setting->mode -= iki_write_mode_to_combining_e; + } + + if (setting->mode & iki_write_mode_to_width_e) { + setting->mode -= iki_write_mode_to_width_e; + } + + setting->mode |= iki_write_mode_to_codepoint_e; + } + else if (choices.array[choice] == iki_write_parameter_to_combining_e) { + if (setting->mode & iki_write_mode_to_bytesequence_e) { + setting->mode -= iki_write_mode_to_bytesequence_e; + } + + if (setting->mode & iki_write_mode_to_codepoint_e) { + setting->mode -= iki_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[iki_write_parameter_to_width_e].result == f_console_result_found_e) { + setting->mode |= iki_write_mode_to_width_e; + } + + setting->mode |= iki_write_mode_to_combining_e; + } + else if (choices.array[choice] == iki_write_parameter_to_width_e) { + if (setting->mode & iki_write_mode_to_bytesequence_e) { + setting->mode -= iki_write_mode_to_bytesequence_e; + } + + if (setting->mode & iki_write_mode_to_codepoint_e) { + setting->mode -= iki_write_mode_to_codepoint_e; + } + + // --to_width may be specified with --to_combining. + if (main->parameters.array[iki_write_parameter_to_combining_e].result == f_console_result_found_e) { + setting->mode |= iki_write_mode_to_combining_e; + } + + setting->mode |= iki_write_mode_to_width_e; + } + } + } + + f_string_static_t * const args = main->parameters.arguments.array; + + if (main->parameters.array[iki_write_parameter_to_file_e].result == f_console_result_additional_e) { + if (main->parameters.array[iki_write_parameter_to_file_e].values.used > 1) { + iki_write_print_error_parameter_file_to_too_many(main, setting); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (args[main->parameters.array[iki_write_parameter_to_file_e].values.array[0]].used) { + setting->path_files_to.used = 0; + + setting->status = f_string_dynamics_increase_by(1, &setting->path_files_to); + if (F_status_is_error(setting->status)) return; + + setting->path_files_to.array[setting->path_files_to.used].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[main->parameters.array[iki_write_parameter_to_file_e].values.array[0]], &setting->path_files_to.array[0]); + if (F_status_is_error(setting->status)) return; + + ++setting->path_files_to.used; + + setting->status = f_file_stream_open(args[main->parameters.array[iki_write_parameter_to_file_e].values.array[0]], f_file_open_mode_append_s, &main->output.to); + + if (F_status_is_error(setting->status)) { + fll_error_file_print(main->error, F_status_set_fine(setting->status), "f_file_stream_open", F_true, args[main->parameters.array[iki_write_parameter_to_file_e].values.array[0]], f_file_operation_open_s, fll_error_file_type_file_e); + + return; + } + + setting->flag |= iki_write_main_flag_file_to_e; + } + else { + iki_write_print_error_parameter_file_name_empty(main, setting, main->parameters.array[iki_write_parameter_to_file_e].values.array[0]); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (main->parameters.array[iki_write_parameter_to_file_e].result == f_console_result_found_e) { + iki_write_print_error_no_value(main, setting, iki_write_long_to_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + main->output.to = main->message.to; + + if (setting->flag & iki_write_main_flag_file_to_e) { + setting->flag -= iki_write_main_flag_file_to_e; + } + } + + if (main->parameters.array[iki_write_parameter_from_file_e].result == f_console_result_additional_e) { + setting->path_files_from.used = 0; + + setting->status = f_string_dynamics_increase_by(main->parameters.array[iki_write_parameter_from_file_e].values.used, &setting->path_files_from); + if (F_status_is_error(setting->status)) return; + + setting->path_files_from.used = main->parameters.array[iki_write_parameter_from_file_e].values.used; + + f_array_length_t i = 0; + f_array_length_t index = 0; + + for (; i < setting->path_files_from.used; ++i) { + + index = main->parameters.array[iki_write_parameter_from_file_e].values.array[i]; + setting->path_files_from.array[i].used = 0; + + setting->status = f_string_dynamic_append_nulless(main->parameters.arguments.array[index], &setting->path_files_from.array[i]); + if (F_status_is_error(setting->status)) return; + + if (args[index].used) { + if (f_file_exists(args[index], F_true) != F_true) { + iki_write_print_error_parameter_file_not_found(main, setting, F_true, args[index]); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_file_found_not); + } + } + } + else { + iki_write_print_error_parameter_file_name_empty(main, setting, index); + + if (F_status_is_error_not(setting->status)) { + setting->status = F_status_set_error(F_parameter); + } + } + } // for + + if (F_status_is_error(setting->status)) return; + + setting->flag |= iki_write_main_flag_file_from_e; + } + else if (main->parameters.array[iki_write_parameter_from_file_e].result == f_console_result_found_e) { + iki_write_print_error_no_value(main, setting, iki_write_long_from_file_s); + + setting->status = F_status_set_error(F_parameter); + + return; + } + else { + if (setting->flag & iki_write_main_flag_file_from_e) { + setting->flag -= iki_write_main_flag_file_from_e; + } + } + + if (F_status_is_error(setting->status)) return; + + if (main->parameters.array[iki_write_parameter_from_file_e].result == f_console_result_none_e && !((main->pipe & fll_program_data_pipe_input_e) || main->parameters.remaining.used)) { + iki_write_print_error_no_from(main, setting); + + setting->status = F_status_set_error(F_parameter); + } + + if (!(setting->mode & iki_write_mode_to_bytesequence_e)) { + if (main->parameters.array[iki_write_parameter_separate_e].result == f_console_result_found_e || main->parameters.array[iki_write_parameter_headers_e].result == f_console_result_found_e) { + setting->prepend = iki_write_string_prepend_padding_s; + setting->append = f_string_eol_s; + } + else { + setting->prepend = f_string_space_s; + } + } + + if (main->parameters.array[iki_write_parameter_headers_e].result == f_console_result_found_e) { + setting->flag |= iki_write_main_flag_header_e; + } + + if (main->parameters.array[iki_write_parameter_separate_e].result == f_console_result_found_e) { + setting->flag |= iki_write_main_flag_separate_e; + } + + if (main->parameters.array[iki_write_parameter_strip_invalid_e].result == f_console_result_found_e) { + setting->flag |= iki_write_main_flag_strip_invalid_e; + } + + setting->valid_not = main->message.set->error; + } +#endif // _di_iki_write_setting_load_ + +#ifndef _di_iki_write_setting_unload_ + f_status_t iki_write_setting_unload(fll_program_data_t * const main, iki_write_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + iki_write_setting_delete(setting); + + return F_none; + } +#endif // _di_iki_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_write/c/common.h b/level_3/iki_write/c/common.h index c2562ce..0da4da3 100644 --- a/level_3/iki_write/c/common.h +++ b/level_3/iki_write/c/common.h @@ -152,6 +152,132 @@ extern "C" { #define iki_write_total_parameters_d 17 #endif // _di_iki_write_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * iki_write_main_flag_*_e: + * - none: No modes in use. + * - file_from: Using a specified source file. + * - file_to: Using a specified destination file. + * - help: Print help. + * - header: Enable printing of headers. + * - separate: Enable printing of separators. + * - strip_invalid: Using strip invalid character mode. + * - verify: Using verify mode. + * - version: Print version. + */ +#ifndef _di_iki_write_main_flag_e_ + enum { + iki_write_main_flag_none_e = 0x0, + iki_write_main_flag_file_from_e = 0x1, + iki_write_main_flag_file_to_e = 0x2, + iki_write_main_flag_header_e = 0x4, + iki_write_main_flag_help_e = 0x8, + iki_write_main_flag_separate_e = 0x10, + iki_write_main_flag_strip_invalid_e = 0x20, + iki_write_main_flag_verify_e = 0x40, + iki_write_main_flag_version_e = 0x80, + }; +#endif // _di_iki_write_main_flag_e_ + +/** + * The iki write main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_iki_write_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } iki_write_setting_t; + + #define iki_write_setting_t_initialize \ + { \ + iki_write_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_iki_write_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_iki_write_setting_delete_ + extern f_status_t iki_write_setting_delete(iki_write_setting_t * const setting); +#endif // _di_iki_write_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_iki_write_setting_load_ + extern void iki_write_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, iki_write_setting_t * const setting); +#endif // _di_iki_write_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_iki_write_setting_unload_ + extern f_status_t iki_write_setting_unload(fll_program_data_t * const main, iki_write_setting_t * const setting); +#endif // _di_iki_write_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_write/c/iki_write.c b/level_3/iki_write/c/iki_write.c index 2497a3c..c265da3 100644 --- a/level_3/iki_write/c/iki_write.c +++ b/level_3/iki_write/c/iki_write.c @@ -6,59 +6,8 @@ extern "C" { #endif -#ifndef _di_iki_write_print_help_ - f_status_t iki_write_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, iki_write_program_name_long_s, iki_write_program_version_s); - - fll_program_print_help_option(file, context, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message."); - fll_program_print_help_option(file, context, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds."); - fll_program_print_help_option(file, context, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds."); - fll_program_print_help_option(file, context, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Do not print using color."); - fll_program_print_help_option(file, context, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, silencing most output."); - fll_program_print_help_option(file, context, f_console_standard_short_error_s, f_console_standard_long_error_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, using only error output."); - fll_program_print_help_option(file, context, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal."); - fll_program_print_help_option(file, context, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal output."); - fll_program_print_help_option(file, context, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, significantly increasing verbosity beyond normal output."); - fll_program_print_help_option(file, context, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number."); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, iki_write_short_file_s, iki_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); - fll_program_print_help_option(file, context, iki_write_short_content_s, iki_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); - fll_program_print_help_option(file, context, iki_write_short_double_s, iki_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); - fll_program_print_help_option(file, context, iki_write_short_object_s, iki_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); - fll_program_print_help_option(file, context, iki_write_short_single_s, iki_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); - - fll_program_print_help_usage(file, context, iki_write_program_name_s, f_string_empty_s); - - fl_print_format("%r %[Notes:%]%r", file.stream, f_string_eol_s, context.set.important, context.set.important, f_string_eol_s); - fl_print_format(" This program will accept Object and Content strings to generate an IKI string, such as %[object:\"content\"%].%r", file.stream, context.set.notable, context.set.notable, f_string_eol_s); - - fl_print_format(" Each object must have a Content (and each Content must have an Object).%r%r", file.stream, f_string_eol_s, f_string_eol_s); - - fl_print_format(" When piping main to this program, a single form-feed character (\\f) must be used to separate each Object from each Content.%r", file.stream, f_string_eol_s); - fl_print_format(" Furthermore, each Object must be followed by a Content.%r", file.stream, f_string_eol_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_iki_write_print_help_ - #ifndef _di_iki_write_main_ - f_status_t iki_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { + f_status_t iki_write_main(fll_program_data_t * const main, iki_write_setting_t * const setting) { f_status_t status = F_none; @@ -112,7 +61,7 @@ extern "C" { status = F_none; if (main->parameters.array[iki_write_parameter_help_e].result == f_console_result_found_e) { - iki_write_print_help(main->output.to, main->context); + iki_write_print_help(setting, main->message); iki_write_data_delete(&data); @@ -120,7 +69,7 @@ extern "C" { } if (main->parameters.array[iki_write_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, iki_write_program_version_s); + fll_program_print_version(main->message, iki_write_program_version_s); iki_write_data_delete(&data); @@ -430,7 +379,7 @@ extern "C" { } if (main->parameters.array[iki_write_parameter_file_e].result == f_console_result_additional_e) { - f_file_stream_flush(file); + f_file_stream_flush(output); f_file_stream_close(&file); } diff --git a/level_3/iki_write/c/iki_write.h b/level_3/iki_write/c/iki_write.h index 58fab70..3251550 100644 --- a/level_3/iki_write/c/iki_write.h +++ b/level_3/iki_write/c/iki_write.h @@ -58,21 +58,6 @@ extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_iki_write_print_help_ - extern f_status_t iki_write_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_iki_write_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -85,16 +70,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_iki_write_main_ - extern f_status_t iki_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern f_status_t iki_write_main(fll_program_data_t * const main, iki_write_setting_t * const setting); #endif // _di_iki_write_main_ #ifdef __cplusplus diff --git a/level_3/iki_write/c/main.c b/level_3/iki_write/c/main.c index f6b68d1..fa672df 100644 --- a/level_3/iki_write/c/main.c +++ b/level_3/iki_write/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + iki_write_setting_t setting = iki_write_setting_t_initialize; f_console_parameter_t parameters[] = iki_write_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = iki_write_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = iki_write_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + iki_write_setting_load(arguments, &data, &setting); + } + + iki_write_main(&data, &setting); + + iki_write_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return F_status_is_error(status) ? 1 : 0; } diff --git a/level_3/iki_write/c/print.c b/level_3/iki_write/c/print.c new file mode 100644 index 0000000..0249187 --- /dev/null +++ b/level_3/iki_write/c/print.c @@ -0,0 +1,88 @@ +#include "iki_write.h" +#include "private-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_iki_write_print_help_ + f_status_t iki_write_print_help(iki_write_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, iki_write_program_name_long_s, iki_write_program_version_s); + + fll_program_print_help_option(print, f_console_standard_short_help_s, f_console_standard_long_help_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print this help message."); + fll_program_print_help_option(print, f_console_standard_short_dark_s, f_console_standard_long_dark_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on dark backgrounds."); + fll_program_print_help_option(print, f_console_standard_short_light_s, f_console_standard_long_light_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Output using colors that show up better on light backgrounds."); + fll_program_print_help_option(print, f_console_standard_short_no_color_s, f_console_standard_long_no_color_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, "Do not print using color."); + fll_program_print_help_option(print, f_console_standard_short_quiet_s, f_console_standard_long_quiet_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, silencing most output."); + fll_program_print_help_option(print, f_console_standard_short_error_s, f_console_standard_long_error_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Decrease verbosity, using only error output."); + fll_program_print_help_option(print, f_console_standard_short_normal_s, f_console_standard_long_normal_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Set verbosity to normal."); + fll_program_print_help_option(print, f_console_standard_short_verbose_s, f_console_standard_long_verbose_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Increase verbosity beyond normal output."); + fll_program_print_help_option(print, f_console_standard_short_debug_s, f_console_standard_long_debug_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Enable debugging, significantly increasing verbosity beyond normal output."); + fll_program_print_help_option(print, f_console_standard_short_version_s, f_console_standard_long_version_s, f_console_symbol_short_disable_s, f_console_symbol_long_disable_s, " Print only the version number."); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, iki_write_short_file_s, iki_write_long_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Specify a file to send data to."); + fll_program_print_help_option(print, iki_write_short_content_s, iki_write_long_content_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The Content to write."); + fll_program_print_help_option(print, iki_write_short_double_s, iki_write_long_double_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use double quotes (default)."); + fll_program_print_help_option(print, iki_write_short_object_s, iki_write_long_object_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The Object to write."); + fll_program_print_help_option(print, iki_write_short_single_s, iki_write_long_single_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use single quotes."); + + fll_program_print_help_usage(print, iki_write_program_name_s, f_string_empty_s); + + fl_print_format("%r %[Notes:%]%r", print.to.stream, f_string_eol_s, print.set->important, print.set->important, f_string_eol_s); + fl_print_format(" This program will accept Object and Content strings to generate an IKI string, such as %[object:\"content\"%].%r", print.to.stream, print.set->notable, print.set->notable, f_string_eol_s); + + fl_print_format(" Each object must have a Content (and each Content must have an Object).%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); + + fl_print_format(" When piping main to this program, a single form-feed character (\\f) must be used to separate each Object from each Content.%r", print.to.stream, f_string_eol_s); + fl_print_format(" Furthermore, each Object must be followed by a Content.%r", print.to.stream, f_string_eol_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_iki_write_print_help_ + +#ifndef _di_iki_write_print_line_first_ + void iki_write_print_line_first(iki_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_iki_write_print_line_first_ + +#ifndef _di_iki_write_print_line_last_ + void iki_write_print_line_last(iki_write_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + if (setting->flag & iki_write_main_flag_verify_e) return; + if ((setting->flag & iki_write_main_flag_file_to_e) && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_iki_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/iki_write/c/print.h b/level_3/iki_write/c/print.h new file mode 100644 index 0000000..7d27db1 --- /dev/null +++ b/level_3/iki_write/c/print.h @@ -0,0 +1,71 @@ +/** + * FLL - Level 3 + * + * Project: UTF-8 + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _iki_write_print_h +#define _iki_write_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_iki_write_print_help_ + extern f_status_t iki_write_print_help(iki_write_setting_t * const setting, const fl_print_t print); +#endif // _di_iki_write_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_iki_write_print_line_first_ + extern void iki_write_print_line_first(iki_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_iki_write_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_iki_write_print_line_last_ + extern void iki_write_print_line_last(iki_write_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_iki_write_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _iki_write_print_h diff --git a/level_3/iki_write/c/private-common.c b/level_3/iki_write/c/private-common.c index 5168e72..a14b2d9 100644 --- a/level_3/iki_write/c/private-common.c +++ b/level_3/iki_write/c/private-common.c @@ -12,24 +12,6 @@ extern "C" { } #endif // _di_iki_write_data_delete_ -#ifndef _di_iki_write_print_signal_received_ - void iki_write_print_signal_received(iki_write_data_t * const data) { - - if (data->main->warning.verbosity != f_console_verbosity_verbose_e && data->main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(data->main->warning.to.stream); - - flockfile(data->main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", data->main->warning.to.stream, data->main->context.set.reset, f_string_eol_s, f_string_eol_s, data->main->context.set.warning, data->main->context.set.warning); - fl_print_format("%[%i%]", data->main->warning.to.stream, data->main->context.set.notable, data->main->signal, data->main->context.set.notable); - fl_print_format("%[.%]%r", data->main->warning.to.stream, data->main->context.set.warning, data->main->context.set.warning, f_string_eol_s); - - funlockfile(data->main->warning.to.stream); - } -#endif // _di_iki_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_write/c/private-common.h b/level_3/iki_write/c/private-common.h index 5ec92d6..54c0945 100644 --- a/level_3/iki_write/c/private-common.h +++ b/level_3/iki_write/c/private-common.h @@ -60,16 +60,6 @@ extern "C" { extern void iki_write_data_delete(iki_write_data_t *data) F_attribute_visibility_internal_d; #endif // _di_iki_write_data_delete_ -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param data - * The program data. - */ -#ifndef _di_iki_write_print_signal_received_ - extern void iki_write_print_signal_received(iki_write_data_t * const data) F_attribute_visibility_internal_d; -#endif // _di_iki_write_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/iki_write/c/private-write.c b/level_3/iki_write/c/private-write.c index 0cc2b77..8e5db8f 100644 --- a/level_3/iki_write/c/private-write.c +++ b/level_3/iki_write/c/private-write.c @@ -7,7 +7,7 @@ extern "C" { #endif #ifndef _di_iki_write_process_ - f_status_t iki_write_process(iki_write_data_t * const data, const f_file_t output, const f_string_static_t object, const f_string_static_t content, f_string_dynamic_t *escaped) { + f_status_t iki_write_process(fll_program_data_t * const main, status_code_setting_t * const setting, iki_write_data_t * const data, const f_file_t output, const f_string_static_t object, const f_string_static_t content, f_string_dynamic_t *escaped) { if (!object.used) { if (data->main->error.verbosity != f_console_verbosity_quiet_e) { diff --git a/level_3/iki_write/c/private-write.h b/level_3/iki_write/c/private-write.h index a778a18..1743b9b 100644 --- a/level_3/iki_write/c/private-write.h +++ b/level_3/iki_write/c/private-write.h @@ -31,7 +31,7 @@ extern "C" { * F_failure (with error bit) for any othe failure. */ #ifndef _di_iki_write_process_ - extern f_status_t iki_write_process(iki_write_data_t * const data, const f_file_t output, const f_string_static_t object, const f_string_static_t content, f_string_dynamic_t *escaped) F_attribute_visibility_internal_d; + extern f_status_t iki_write_process(fll_program_data_t * const main, status_code_setting_t * const setting, iki_write_data_t * const data, const f_file_t output, const f_string_static_t object, const f_string_static_t content, f_string_dynamic_t *escaped) F_attribute_visibility_internal_d; #endif // _di_iki_write_process_ #ifdef __cplusplus diff --git a/level_3/iki_write/data/build/settings b/level_3/iki_write/data/build/settings index 4f28021..801023a 100644 --- a/level_3/iki_write/data/build/settings +++ b/level_3/iki_write/data/build/settings @@ -21,11 +21,11 @@ build_libraries-individual -lfll_error -lfll_iki -lfll_print -lfll_program -lfl_ build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library iki_write.c common.c private-common.c private-write.c +build_sources_library iki_write.c common.c print.c private-common.c private-write.c build_sources_program main.c -build_sources_headers iki_write.h common.h +build_sources_headers iki_write.h common.h print.h build_script yes build_shared yes diff --git a/level_3/status_code/c/common.c b/level_3/status_code/c/common.c index abccb6d..f646606 100644 --- a/level_3/status_code/c/common.c +++ b/level_3/status_code/c/common.c @@ -17,6 +17,16 @@ extern "C" { const f_string_static_t status_code_program_help_parameters_s = macro_f_string_static_t_initialize(STATUS_CODE_program_help_parameters_s, 0, STATUS_CODE_program_help_parameters_s_length); #endif // _di_status_code_program_help_parameters_ +#ifndef _di_status_code_strings_ + const f_string_static_t status_code_failed_to_convert_s = macro_f_string_static_t_initialize(STATUS_CODE_failed_to_convert_s, 0, STATUS_CODE_failed_to_convert_s_length); + const f_string_static_t status_code_invalid_number_s = macro_f_string_static_t_initialize(STATUS_CODE_invalid_number_s, 0, STATUS_CODE_invalid_number_s_length); + const f_string_static_t status_code_invalid_name_s = macro_f_string_static_t_initialize(STATUS_CODE_invalid_number_s, 0, STATUS_CODE_invalid_number_s_length); + const f_string_static_t status_code_invalid_main_s = macro_f_string_static_t_initialize(STATUS_CODE_invalid_main_s, 0, STATUS_CODE_invalid_main_s_length); + const f_string_static_t status_code_out_of_range_s = macro_f_string_static_t_initialize(STATUS_CODE_out_of_range_s, 0, STATUS_CODE_out_of_range_s_length); + const f_string_static_t status_code_unknown_code_s = macro_f_string_static_t_initialize(STATUS_CODE_unknown_code_s, 0, STATUS_CODE_unknown_code_s_length); + const f_string_static_t status_code_unknown_name_s = macro_f_string_static_t_initialize(STATUS_CODE_unknown_name_s, 0, STATUS_CODE_unknown_name_s_length); +#endif // _di_status_code_strings_ + #ifndef _di_status_code_parameters_ const f_string_static_t status_code_short_fine_s = macro_f_string_static_t_initialize(STATUS_CODE_short_fine_s, 0, STATUS_CODE_short_fine_s_length); const f_string_static_t status_code_short_warning_s = macro_f_string_static_t_initialize(STATUS_CODE_short_warning_s, 0, STATUS_CODE_short_warning_s_length); @@ -29,6 +39,165 @@ extern "C" { const f_string_static_t status_code_long_number_s = macro_f_string_static_t_initialize(STATUS_CODE_long_number_s, 0, STATUS_CODE_long_number_s_length); #endif // _di_status_code_parameters_ +#ifndef _di_status_code_setting_delete_ + f_status_t status_code_setting_delete(status_code_setting_t * const setting) { + + if (!setting) return F_status_set_error(F_parameter); + + return F_none; + } +#endif // _di_status_code_setting_delete_ + +#ifndef _di_status_code_setting_load_ + void status_code_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, status_code_setting_t * const setting) { + + if (!main || !setting) return; + + // Load parameters. + setting->status = f_console_parameter_process(arguments, &main->parameters); + if (F_status_is_error(setting->status)) return; + + { + f_array_length_t choice = 0; + f_uint16s_t choices = f_uint16s_t_initialize; + + // Identify and prioritize "color context" parameters. + { + uint16_t choices_array[3] = { status_code_parameter_no_color_e, status_code_parameter_light_e, status_code_parameter_dark_e }; + choices.array = choices_array; + choices.used = 3; + + const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; + + setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); + + if (F_status_is_error(setting->status)) { + status_code_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + status_code_print_line_last(setting, main->error, F_true); + + return; + } + } + + if (main->parameters.array[status_code_parameter_line_first_no_e].result == f_console_result_found_e) { + setting->line_first = f_string_empty_s; + } + else { + setting->line_first = f_string_eol_s; + } + + if (main->parameters.array[status_code_parameter_line_last_no_e].result == f_console_result_found_e) { + setting->line_last = f_string_empty_s; + } + else { + setting->line_last = f_string_eol_s; + } + + // Identify and prioritize "verbosity" parameters. + { + uint16_t choices_array[5] = { status_code_parameter_verbosity_quiet_e, status_code_parameter_verbosity_error_e, status_code_parameter_verbosity_verbose_e, status_code_parameter_verbosity_debug_e, status_code_parameter_verbosity_normal_e }; + choices.array = choices_array; + choices.used = 5; + + const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + + setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); + + if (F_status_is_error(setting->status)) { + status_code_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + status_code_print_line_last(setting, main->error, F_true); + + return; + } + } + + if (main->parameters.array[status_code_parameter_help_e].result == f_console_result_found_e) { + setting->flag |= status_code_main_flag_help_e; + + return; + } + + if (main->parameters.array[status_code_parameter_version_e].result == f_console_result_found_e) { + setting->flag |= status_code_main_flag_version_e; + + return; + } + } + + if (main->parameters.array[status_code_parameter_error_e].result == f_console_result_found_e) { + setting->flag |= status_code_main_flag_error_e; + } + + if (main->parameters.array[status_code_parameter_fine_e].result == f_console_result_found_e) { + setting->flag |= status_code_main_flag_fine_e; + } + + if (main->parameters.array[status_code_parameter_warning_e].result == f_console_result_found_e) { + setting->flag |= status_code_main_flag_warning_e; + } + + if (main->parameters.array[status_code_parameter_number_e].result == f_console_result_found_e) { + setting->flag |= status_code_main_flag_number_e; + } + + if (setting->flag & status_code_main_flag_error_e) { + if (setting->flag & status_code_main_flag_warning_e) { + if (!(setting->flag & status_code_main_flag_number_e)) { + status_code_print_line_first(setting, main->error, F_true); + status_code_print_error_cannot_error_warning_number(setting, main->error); + status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + + if (setting->flag & status_code_main_flag_fine_e) { + status_code_print_line_first(setting, main->error, F_true); + fll_program_parameter_long_print_cannot_use_with(main->error, status_code_long_error_s, status_code_long_fine_s); + status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } + else if (setting->flag & status_code_main_flag_warning_e && setting->flag & status_code_main_flag_fine_e) { + status_code_print_line_first(setting, main->error, F_true); + fll_program_parameter_long_print_cannot_use_with(main->error, status_code_long_warning_s, status_code_long_fine_s); + status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + + if (main->parameters.remaining.used == 0 && !(main->pipe & fll_program_data_pipe_input_e)) { + status_code_print_line_first(setting, main->error, F_true); + status_code_print_error_no_status_codes(setting, main->error); + status_code_print_line_last(setting, main->error, F_true); + + setting->status = F_status_set_error(F_parameter); + + return; + } + } +#endif // _di_status_code_setting_load_ + +#ifndef _di_status_code_setting_unload_ + f_status_t status_code_setting_unload(fll_program_data_t * const main, status_code_setting_t * const setting) { + + if (!main || !setting) return F_status_set_error(F_parameter); + + status_code_setting_delete(setting); + + return F_none; + } +#endif // _di_status_code_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/status_code/c/common.h b/level_3/status_code/c/common.h index 1d77a4b..3030531 100644 --- a/level_3/status_code/c/common.h +++ b/level_3/status_code/c/common.h @@ -70,6 +70,35 @@ extern "C" { #endif // _di_status_code_program_help_parameters_ /** + * Special strings used by this program. + */ +#ifndef _di_status_code_strings_ + #define STATUS_CODE_failed_to_convert_s "failed to convert" + #define STATUS_CODE_invalid_number_s "invalid number" + #define STATUS_CODE_invalid_name_s "invalid name" + #define STATUS_CODE_invalid_main_s "invalid main" + #define STATUS_CODE_out_of_range_s "out of range" + #define STATUS_CODE_unknown_code_s "unknown code" + #define STATUS_CODE_unknown_name_s "unknown name" + + #define STATUS_CODE_failed_to_convert_s_length 17 + #define STATUS_CODE_invalid_number_s_length 14 + #define STATUS_CODE_invalid_name_s_length 12 + #define STATUS_CODE_invalid_main_s_length 12 + #define STATUS_CODE_out_of_range_s_length 12 + #define STATUS_CODE_unknown_code_s_length 12 + #define STATUS_CODE_unknown_name_s_length 12 + + extern const f_string_static_t status_code_failed_to_convert_s; + extern const f_string_static_t status_code_invalid_number_s; + extern const f_string_static_t status_code_invalid_name_s; + extern const f_string_static_t status_code_invalid_main_s; + extern const f_string_static_t status_code_out_of_range_s; + extern const f_string_static_t status_code_unknown_code_s; + extern const f_string_static_t status_code_unknown_name_s; +#endif // _di_status_code_strings_ + +/** * The program defines. */ #ifndef _di_status_code_defines_ @@ -154,6 +183,130 @@ extern "C" { #define status_code_total_parameters_d 16 #endif // _di_status_code_parameters_ +/** + * Flags used to represent flags passed to the main function. + * + * When number mode is not specified, then mode is "string" mode (there is no flag for "string" mode). + * + * status_code_main_flag_*_e: + * - none: No modes in use. + * - error: Check if status is "error". + * - fine: Check if status is "fine". + * - help: Print help. + * - number: Operate in number mode. + * - version: Print version. + * - warning: Check if status is "warning". + */ +#ifndef _di_status_code_main_flag_e_ + enum { + status_code_main_flag_none_e = 0x0, + status_code_main_flag_error_e = 0x1, + status_code_main_flag_fine_e = 0x2, + status_code_main_flag_help_e = 0x4, + status_code_main_flag_number_e = 0x8, + status_code_main_flag_version_e = 0x10, + status_code_main_flag_warning_e = 0x20, + }; +#endif // _di_status_code_main_flag_e_ + +/** + * The status code main program settings. + * + * This is passed to the program-specific main entry point to designate program settings. + * These program settings are often processed from the program arguments (often called the command line arguments). + * + * flag: Flags passed to the main function. + * + * status: The main status code, generally used by the load settings and main functions. + * + * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not. + * line_last: A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not. + */ +#ifndef _di_status_code_setting_t_ + typedef struct { + uint16_t flag; + + f_status_t status; + + f_string_static_t line_first; + f_string_static_t line_last; + } status_code_setting_t; + + #define status_code_setting_t_initialize \ + { \ + status_code_main_flag_none_e, \ + F_none, \ + f_string_static_t_initialize, \ + f_string_static_t_initialize, \ + } +#endif // _di_status_code_setting_t_ + +/** + * Delete the program main setting data. + * + * @param setting + * The program main setting data. + * This does not alter setting.status. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_status_code_setting_delete_ + extern f_status_t status_code_setting_delete(status_code_setting_t * const setting); +#endif // _di_status_code_setting_delete_ + +/** + * Perform the standard program setting load process. + * + * This prints error messages as appropriate. + * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * + * @param arguments + * The parameters passed to the process (often referred to as command line arguments). + * @param main + * The main program data. + * @param setting + * The main program settings. + * + * This alters setting.status: + * F_none on success. + * + * Errors (with error bit) from: f_console_parameter_process(). + * Errors (with error bit) from: fll_program_parameter_process_context(). + * + * @see f_console_parameter_process() + * @see fll_program_parameter_process_context() + */ +#ifndef _di_status_code_setting_load_ + extern void status_code_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, status_code_setting_t * const setting); +#endif // _di_status_code_setting_load_ + +/** + * Perform the standard program setting unload process. + * + * @param main + * The main program data. + * @param setting + * The main program settings. + * This does not alter setting.status. + * All buffers are deallocated. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() + */ +#ifndef _di_status_code_setting_unload_ + extern f_status_t status_code_setting_unload(fll_program_data_t * const main, status_code_setting_t * const setting); +#endif // _di_status_code_setting_unload_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/status_code/c/main.c b/level_3/status_code/c/main.c index 9880216..5c7ac19 100644 --- a/level_3/status_code/c/main.c +++ b/level_3/status_code/c/main.c @@ -2,12 +2,13 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { - const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); fll_program_data_t data = fll_program_data_t_initialize; + status_code_setting_t setting = status_code_setting_t_initialize; f_console_parameter_t parameters[] = status_code_console_parameter_t_initialize; data.parameters.array = parameters; data.parameters.used = status_code_total_parameters_d; + data.environment = envp; if (f_pipe_input_exists()) { data.pipe = fll_program_data_pipe_input_e; @@ -15,13 +16,19 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { fll_program_standard_set_up(&data); - const f_status_t status = status_code_main(&data, arguments); + { + const f_console_arguments_t arguments = macro_f_console_arguments_t_initialize(argc, argv, envp); + + status_code_setting_load(arguments, &data, &setting); + } + + status_code_main(&data, &setting); + + status_code_setting_unload(&data, &setting); fll_program_data_delete(&data); fll_program_standard_set_down(&data); - if (F_status_is_error(status)) return 1; - - return 0; + return (F_status_is_error(setting.status) || setting.status == F_false) ? 1 : 0; } diff --git a/level_3/status_code/c/print.c b/level_3/status_code/c/print.c new file mode 100644 index 0000000..d28b8b1 --- /dev/null +++ b/level_3/status_code/c/print.c @@ -0,0 +1,97 @@ +#include "status_code.h" +#include "private-common.h" +#include "print.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_status_code_print_error_cannot_error_warning_number_ + void status_code_print_error_cannot_error_warning_number(status_code_setting_t * const setting, const fl_print_t print) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + f_file_stream_lock(print.to); + + fl_print_format("%[%QCannot specify the '%]", print.to.stream, print.context, print.prefix, print.context); + fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, status_code_long_error_s, print.notable); + fl_print_format("%[' parameter with the '%]", print.to.stream, print.context, print.context); + fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, status_code_long_warning_s, print.notable); + fl_print_format("%[' parameter when not also specifying the '%]", print.to.stream, print.context, print.context); + fl_print_format("%[%r%r%]", print.to.stream, print.notable, f_console_symbol_long_enable_s, status_code_long_number_s, print.notable); + fl_print_format("%[' parameter.%]%r", print.to.stream, print.context, print.context, f_string_eol_s); + + f_file_stream_unlock(print.to); + } +#endif // _di_status_code_print_error_cannot_error_warning_number_ + +#ifndef _di_status_code_print_error_no_status_codes_ + void status_code_print_error_no_status_codes(status_code_setting_t * const setting, const fl_print_t print) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + fll_print_format("%[No status code is specified.%]%r", print.to.stream, print.context, print.context, f_string_eol_s); + } +#endif // _di_status_code_print_error_no_status_codes_ + +#ifndef _di_status_code_print_help_ + f_status_t status_code_print_help(status_code_setting_t * const setting, const fl_print_t print) { + + f_file_stream_lock(print.to); + + f_print_dynamic_raw(setting->line_first, print.to.stream); + + fll_program_print_help_header(print, status_code_program_name_long_s, status_code_program_version_s); + + fll_program_print_help_option_standard(print); + + f_print_dynamic_raw(f_string_eol_s, print.to.stream); + + fll_program_print_help_option(print, status_code_short_fine_s, status_code_long_fine_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is neither an error nor a warning or print number with neither the error code nor the warning code bits set."); + fll_program_print_help_option(print, status_code_short_warning_s, status_code_long_warning_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print F_true or F_false if status code is a warning or print number with warning code bit set."); + fll_program_print_help_option(print, status_code_short_error_s, status_code_long_error_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is an error or print number with error code bit set."); + fll_program_print_help_option(print, status_code_short_number_s, status_code_long_number_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Convert status code name to number."); + + fll_program_print_help_usage(print, status_code_program_name_s, status_code_program_help_parameters_s); + + f_print_dynamic_raw(setting->line_last, print.to.stream); + + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); + + return F_none; + } +#endif // _di_status_code_print_help_ + +#ifndef _di_status_code_print_line_first_ + void status_code_print_line_first(status_code_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_first, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_first, print.to.stream); + } + } +#endif // _di_status_code_print_line_first_ + +#ifndef _di_status_code_print_line_last_ + void status_code_print_line_last(status_code_setting_t * const setting, const fl_print_t print, const bool lock) { + + if (print.verbosity == f_console_verbosity_quiet_e) return; + if (print.verbosity == f_console_verbosity_error_e && !F_status_is_error(setting->status)) return; + + if (lock) { + fll_print_dynamic_raw(setting->line_last, print.to.stream); + } + else { + f_print_dynamic_raw(setting->line_last, print.to.stream); + } + } +#endif // _di_status_code_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_3/status_code/c/print.h b/level_3/status_code/c/print.h new file mode 100644 index 0000000..e541062 --- /dev/null +++ b/level_3/status_code/c/print.h @@ -0,0 +1,97 @@ +/** + * FLL - Level 3 + * + * Project: Status Code + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + */ +#ifndef _status_code_print_h +#define _status_code_print_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Print an error message when error parameter and warning parameter are specified without number parameter. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + */ +#ifndef _di_status_code_print_error_cannot_error_warning_number_ + extern void status_code_print_error_cannot_error_warning_number(status_code_setting_t * const setting, const fl_print_t print); +#endif // _di_status_code_print_error_cannot_error_warning_number_ + +/** + * Print an error message when no status codes are provided. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + */ +#ifndef _di_status_code_print_error_no_status_codes_ + extern void status_code_print_error_no_status_codes(status_code_setting_t * const setting, const fl_print_t print); +#endif // _di_status_code_print_error_no_status_codes_ + +/** + * Print help. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * The output structure to print to. + * + * @return + * F_none on success. + */ +#ifndef _di_status_code_print_help_ + extern f_status_t status_code_print_help(status_code_setting_t * const setting, const fl_print_t print); +#endif // _di_status_code_print_help_ + +/** + * Print first new line, unless verbosity says otherwise. + * + * This is generally either the first line in the program or the first line printed before an error message. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_status_code_print_line_first_ + extern void status_code_print_line_first(status_code_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_status_code_print_line_first_ + +/** + * Print last new line when the main is complete, unless verbosity says otherwise. + * + * This is generally the very last line printed in the program. + * + * @param setting + * The main program settings. + * This does not alter setting.status. + * @param print + * Designates the how and where to print. + * @param lock + * If TRUE, then lock the stream. + * If FALSE, then do not lock or unlock the stream. + */ +#ifndef _di_status_code_print_line_last_ + extern void status_code_print_line_last(status_code_setting_t * const setting, const fl_print_t print, const bool lock); +#endif // _di_status_code_print_line_last_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _status_code_print_h diff --git a/level_3/status_code/c/private-common.c b/level_3/status_code/c/private-common.c index 1ee3c476..7540b79 100644 --- a/level_3/status_code/c/private-common.c +++ b/level_3/status_code/c/private-common.c @@ -5,24 +5,6 @@ extern "C" { #endif -#ifndef _di_status_code_print_signal_received_ - void status_code_print_signal_received(fll_program_data_t * const main) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) return; - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - fflush(main->warning.to.stream); - - flockfile(main->warning.to.stream); - - fl_print_format("%]%r%r%[Received signal code %]", main->warning.to.stream, main->context.set.reset, f_string_eol_s, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, main->signal_received, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_status_code_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/status_code/c/private-common.h b/level_3/status_code/c/private-common.h index 6a1589d..dc1d6a4 100644 --- a/level_3/status_code/c/private-common.h +++ b/level_3/status_code/c/private-common.h @@ -12,16 +12,6 @@ extern "C" { #endif -/** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - */ -#ifndef _di_status_code_print_signal_received_ - extern void status_code_print_signal_received(fll_program_data_t * const main) F_attribute_visibility_internal_d; -#endif // _di_status_code_print_signal_received_ - #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/status_code/c/private-status_code.c b/level_3/status_code/c/private-status_code.c index 5054717..24684d3 100644 --- a/level_3/status_code/c/private-status_code.c +++ b/level_3/status_code/c/private-status_code.c @@ -7,50 +7,30 @@ extern "C" { #endif #ifndef _di_status_code_process_check_ - f_status_t status_code_process_check(fll_program_data_t * const main, const f_string_static_t value) { + f_status_t status_code_process_check(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value) { f_number_unsigned_t number = 0; - f_status_t status = status_code_convert_number(main, value, &number); - if (F_status_is_error(status)) return status; - - if (main->parameters.array[status_code_parameter_error_e].result == f_console_result_found_e) { - if (F_status_is_error(number)) { - f_print_dynamic_raw(f_status_true_s, main->output.to.stream); - } - else { - f_print_dynamic_raw(f_status_false_s, main->output.to.stream); - } - - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + { + f_status_t status = status_code_convert_number(main, setting, value, &number); + if (F_status_is_error(status)) return status; } - else if (main->parameters.array[status_code_parameter_warning_e].result == f_console_result_found_e) { - if (F_status_is_warning(number)) { - f_print_dynamic_raw(f_status_true_s, main->output.to.stream); - } - else { - f_print_dynamic_raw(f_status_false_s, main->output.to.stream); - } - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + if ((setting->flag & status_code_main_flag_error_e) && F_status_is_error(number) || (setting->flag & status_code_main_flag_warning_e) && F_status_is_warning(number) || (setting->flag & status_code_main_flag_fine_e) && F_status_is_fine(number)) { + f_print_dynamic_raw(f_status_true_s, main->output.to.stream); } - else if (main->parameters.array[status_code_parameter_fine_e].result == f_console_result_found_e) { - if (F_status_is_fine(number)) { - f_print_dynamic_raw(f_status_true_s, main->output.to.stream); - } - else { - f_print_dynamic_raw(f_status_false_s, main->output.to.stream); - } - - f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + else { + f_print_dynamic_raw(f_status_false_s, main->output.to.stream); } + f_print_dynamic_raw(f_string_eol_s, main->output.to.stream); + return F_none; } #endif // _di_status_code_process_check_ #ifndef _di_status_code_process_number_ - f_status_t status_code_process_number(fll_program_data_t * const main, const f_string_static_t value) { + f_status_t status_code_process_number(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value) { f_status_t status = F_none; @@ -60,13 +40,13 @@ extern "C" { status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, value, &number); if (status == F_none) { - fl_print_format("%[invalid name%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_invalid_name_s, main->context.set.error, f_string_eol_s); return F_status_set_error(F_parameter); } if (status == F_data_not || F_status_set_fine(status) == F_parameter) { - fl_print_format("%[invalid main%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_invalid_main_s, main->context.set.error, f_string_eol_s); return status; } @@ -78,26 +58,26 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown name%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_unknown_name_s, main->context.set.error, f_string_eol_s); } else { - fl_print_format("%[failed to convert%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_failed_to_convert_s, main->context.set.error, f_string_eol_s); } return status; } if (status == F_data) { - fl_print_format("%[unknown code%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_unknown_code_s, main->context.set.error, f_string_eol_s); return F_none; } - if (main->parameters.array[status_code_parameter_error_e].result == f_console_result_found_e) { + if (setting->flag & status_code_main_flag_error_e) { code = F_status_set_error(code); } - if (main->parameters.array[status_code_parameter_warning_e].result == f_console_result_found_e) { + if (setting->flag & status_code_main_flag_warning_e) { code = F_status_set_warning(code); } @@ -108,11 +88,11 @@ extern "C" { #endif // _di_status_code_process_number_ #ifndef _di_status_code_process_normal_ - f_status_t status_code_process_normal(fll_program_data_t * const main, const f_string_static_t value) { + f_status_t status_code_process_normal(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value) { f_number_unsigned_t number = 0; - f_status_t status = status_code_convert_number(main, value, &number); + f_status_t status = status_code_convert_number(main, setting, value, &number); if (F_status_is_error(status)) return status; f_string_static_t name = f_string_static_t_initialize; @@ -121,10 +101,10 @@ extern "C" { if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_data) { - fl_print_format("%[unknown code%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_unknown_code_s, main->context.set.error, f_string_eol_s); } else { - fl_print_format("%[failed to convert%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_failed_to_convert_s, main->context.set.error, f_string_eol_s); } return status; @@ -137,22 +117,22 @@ extern "C" { #endif // _di_status_code_process_normal_ #ifndef _di_status_code_convert_number_ - f_status_t status_code_convert_number(fll_program_data_t * const main, const f_string_static_t value, f_number_unsigned_t *number) { + f_status_t status_code_convert_number(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value, f_number_unsigned_t *number) { - f_status_t status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, value, number); + const f_status_t status = fl_conversion_dynamic_to_unsigned_detect(fl_conversion_data_base_10_c, value, number); if (*number > F_status_size_max_with_bits_d) { - fl_print_format("%[out of range%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_out_of_range_s, main->context.set.error, f_string_eol_s); return F_status_set_error(F_number_overflow); } if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_number_negative) { - fl_print_format("%[out of range%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_out_of_range_s, main->context.set.error, f_string_eol_s); } else { - fl_print_format("%[invalid number%]%r", main->output.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); + fl_print_format("%[%r%]%r", main->output.to.stream, main->context.set.error, status_code_invalid_number_s, main->context.set.error, f_string_eol_s); } return status; diff --git a/level_3/status_code/c/private-status_code.h b/level_3/status_code/c/private-status_code.h index acfa72c..889ea70 100644 --- a/level_3/status_code/c/private-status_code.h +++ b/level_3/status_code/c/private-status_code.h @@ -34,7 +34,7 @@ extern "C" { * @see fss_status_code_convert_number() */ #ifndef _di_status_code_process_check_ - extern f_status_t status_code_process_check(fll_program_data_t * const main, const f_string_static_t value) F_attribute_visibility_internal_d; + extern f_status_t status_code_process_check(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value) F_attribute_visibility_internal_d; #endif // _di_status_code_process_check_ /** @@ -56,7 +56,7 @@ extern "C" { * @see fll_fss_status_string_from() */ #ifndef _di_status_code_process_number_ - extern f_status_t status_code_process_number(fll_program_data_t * const main, const f_string_static_t value) F_attribute_visibility_internal_d; + extern f_status_t status_code_process_number(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value) F_attribute_visibility_internal_d; #endif // _di_status_code_process_number_ /** @@ -83,7 +83,7 @@ extern "C" { * @see fss_status_code_convert_number() */ #ifndef _di_status_code_process_normal_ - extern f_status_t status_code_process_normal(fll_program_data_t * const main, const f_string_static_t value) F_attribute_visibility_internal_d; + extern f_status_t status_code_process_normal(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value) F_attribute_visibility_internal_d; #endif // _di_status_code_process_normal_ /** @@ -111,7 +111,7 @@ extern "C" { * @see fl_console_parameter_to_number_unsigned() */ #ifndef _di_status_code_convert_number_ - extern f_status_t status_code_convert_number(fll_program_data_t * const main, const f_string_static_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; + extern f_status_t status_code_convert_number(fll_program_data_t * const main, status_code_setting_t * const setting, const f_string_static_t value, f_number_unsigned_t *number) F_attribute_visibility_internal_d; #endif // _di_status_code_convert_number_ #ifdef __cplusplus diff --git a/level_3/status_code/c/status_code.c b/level_3/status_code/c/status_code.c index 620d0e8..94fe552 100644 --- a/level_3/status_code/c/status_code.c +++ b/level_3/status_code/c/status_code.c @@ -6,165 +6,52 @@ extern "C" { #endif -#ifndef _di_status_code_print_help_ - f_status_t status_code_print_help(const f_file_t file, const f_color_context_t context) { - - flockfile(file.stream); - - //if (!(setting->flag & XXX_main_flag_line_first_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - fll_program_print_help_header(file, context, status_code_program_name_long_s, status_code_program_version_s); - - fll_program_print_help_option_standard(file, context); - - f_print_dynamic_raw(f_string_eol_s, file.stream); - - fll_program_print_help_option(file, context, status_code_short_fine_s, status_code_long_fine_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is neither an error nor a warning or print number with neither the error code nor the warning code bits set."); - fll_program_print_help_option(file, context, status_code_short_warning_s, status_code_long_warning_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Print F_true or F_false if status code is a warning or print number with warning code bit set."); - fll_program_print_help_option(file, context, status_code_short_error_s, status_code_long_error_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print F_true or F_false if status code is an error or print number with error code bit set."); - fll_program_print_help_option(file, context, status_code_short_number_s, status_code_long_number_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Convert status code name to number."); - - fll_program_print_help_usage(file, context, status_code_program_name_s, status_code_program_help_parameters_s); - - //if (!(setting->flag & XXX_main_flag_line_last_no_e)) { - f_print_dynamic_raw(f_string_eol_s, file.stream); - //} - - f_file_stream_flush(file); - funlockfile(file.stream); - - return F_none; - } -#endif // _di_status_code_print_help_ - #ifndef _di_status_code_main_ - f_status_t status_code_main(fll_program_data_t * const main, const f_console_arguments_t arguments) { - - f_status_t status = F_none; - - // Load parameters. - status = f_console_parameter_process(arguments, &main->parameters); - if (F_status_is_error(status)) return; - - { - f_array_length_t choice = 0; - f_uint16s_t choices = f_uint16s_t_initialize; - - // Identify and prioritize "color context" parameters. - { - uint16_t choices_array[3] = { status_code_parameter_no_color_e, status_code_parameter_light_e, status_code_parameter_dark_e }; - choices.array = choices_array; - choices.used = 3; - - const uint8_t modes[3] = { f_color_mode_color_not_e, f_color_mode_light_e, f_color_mode_dark_e }; - - status = fll_program_parameter_process_context(choices, modes, F_true, main); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_context", F_true); - - return; - } - } + void status_code_main(fll_program_data_t * const main, status_code_setting_t * const setting) { - // Identify and prioritize "verbosity" parameters. - { - uint16_t choices_array[5] = { status_code_parameter_verbosity_quiet_e, status_code_parameter_verbosity_error_e, status_code_parameter_verbosity_verbose_e, status_code_parameter_verbosity_debug_e, status_code_parameter_verbosity_normal_e }; - choices.array = choices_array; - choices.used = 5; + if (!main || !setting) { + status_code_print_line_first(setting, main->error, F_true); + fll_error_print(main->error, F_parameter, "status_code_main", F_true); + status_code_print_line_last(setting, main->error, F_true); - const uint8_t verbosity[5] = { f_console_verbosity_quiet_e, f_console_verbosity_error_e, f_console_verbosity_verbose_e, f_console_verbosity_debug_e, f_console_verbosity_normal_e }; + setting->status = F_status_set_error(F_parameter); - status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); - - if (F_status_is_error(status)) { - fll_error_print(main->error, F_status_set_fine(status), "fll_program_parameter_process_verbosity", F_true); - - return; - } - } + return; } - f_string_static_t * const argv = main->parameters.arguments.array; + if (F_status_is_error(setting->status)) return; - status = F_none; + setting->status = F_none; - if (main->parameters.array[status_code_parameter_help_e].result == f_console_result_found_e) { - status_code_print_help(main->output.to, main->context); + if (setting->flag & status_code_main_flag_help_e) { + status_code_print_help(setting, main->message); - return F_none; + return; } - if (main->parameters.array[status_code_parameter_version_e].result == f_console_result_found_e) { - fll_program_print_version(main->output.to, status_code_program_version_s); + if (setting->flag & status_code_main_flag_version_e) { + fll_program_print_version(main->message, status_code_program_version_s); - return F_none; - } - - if (main->parameters.array[status_code_parameter_error_e].result == f_console_result_found_e) { - if (main->parameters.array[status_code_parameter_warning_e].result == f_console_result_found_e) { - if (main->parameters.array[status_code_parameter_number_e].result == f_console_result_none_e) { - if (main->error.verbosity != f_console_verbosity_quiet_e) { - flockfile(main->error.to.stream); - - fl_print_format("%r%[%QCannot specify the '%]", main->error.to.stream, f_string_eol_s, main->error.context, main->error.prefix, main->error.context); - fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, status_code_long_error_s, main->error.notable); - fl_print_format("%[' parameter with the '%]", main->error.to.stream, main->error.context, main->error.context); - fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, status_code_long_warning_s, main->error.notable); - fl_print_format("%[' parameter when not also specifying the '%]", main->error.to.stream, main->error.context, main->error.context); - fl_print_format("%[%r%r%]", main->error.to.stream, main->error.notable, f_console_symbol_long_enable_s, status_code_long_number_s, main->error.notable); - fl_print_format("%[' parameter.%]%r%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s, f_string_eol_s); - - funlockfile(main->error.to.stream); - } - - return F_status_set_error(status); - } - } - - if (main->parameters.array[status_code_parameter_fine_e].result == f_console_result_found_e) { - if (main->error.verbosity != f_console_verbosity_quiet_e) { - fll_program_parameter_long_print_cannot_use_with(main->error, status_code_long_error_s, status_code_long_fine_s); - fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); - } - - return F_status_set_error(status); - } - } - else if (main->parameters.array[status_code_parameter_warning_e].result == f_console_result_found_e && main->parameters.array[status_code_parameter_fine_e].result == f_console_result_found_e) { - if (main->error.verbosity != f_console_verbosity_quiet_e) { - fll_program_parameter_long_print_cannot_use_with(main->error, status_code_long_warning_s, status_code_long_fine_s); - fll_print_dynamic_raw(f_string_eol_s, main->error.to.stream); - } - - return F_status_set_error(status); - } - - if (main->parameters.remaining.used == 0 && !(main->pipe & fll_program_data_pipe_input_e)) { - fll_print_format("%[You failed to specify a status code.%]%r", main->error.to.stream, main->error.context, main->error.context, f_string_eol_s); - - return F_status_set_error(F_parameter); + return; } f_status_t status2 = F_none; - if (main->parameters.array[status_code_parameter_number_e].result == f_console_result_found_e) { + if (setting->flag & status_code_main_flag_number_e) { if (main->pipe & fll_program_data_pipe_input_e) { // @todo call status_code_process_number() here for all main from pipe that is space separated. } if (main->parameters.remaining.used) { - flockfile(main->output.to.stream); + f_file_stream_lock(main->output.to); for (f_array_length_t i = 0; i < main->parameters.remaining.used; ++i) { if (!((++main->signal_check) % status_code_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - status_code_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); - status = F_status_set_error(F_signal); + setting->status = F_status_set_error(F_signal); break; } @@ -172,31 +59,31 @@ extern "C" { main->signal_check = 0; } - status2 = status_code_process_number(main, argv[main->parameters.remaining.array[i]]); + status2 = status_code_process_number(main, setting, main->parameters.arguments.array[main->parameters.remaining.array[i]]); - if (F_status_is_error(status2) && status == F_none) { - status = status2; + if (F_status_is_error(status2) && setting->status == F_none) { + setting->status = status2; } } // for - funlockfile(main->output.to.stream); + f_file_stream_unlock(main->output.to); } } - else if (main->parameters.array[status_code_parameter_error_e].result == f_console_result_found_e || main->parameters.array[status_code_parameter_warning_e].result == f_console_result_found_e || main->parameters.array[status_code_parameter_fine_e].result == f_console_result_found_e) { + else if (setting->flag & status_code_main_flag_error_e || setting->flag & status_code_main_flag_warning_e || setting->flag & status_code_main_flag_fine_e) { if (main->pipe & fll_program_data_pipe_input_e) { // @todo call status_code_process_check() here for all main from pipe that is space separated. } if (main->parameters.remaining.used) { - flockfile(main->output.to.stream); + f_file_stream_lock(main->output.to); for (f_array_length_t i = 0; i < main->parameters.remaining.used; ++i) { if (!((++main->signal_check) % status_code_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - status_code_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); - status = F_status_set_error(F_signal); + setting->status = F_status_set_error(F_signal); break; } @@ -204,14 +91,14 @@ extern "C" { main->signal_check = 0; } - status2 = status_code_process_check(main, argv[main->parameters.remaining.array[i]]); + status2 = status_code_process_check(main, setting, main->parameters.arguments.array[main->parameters.remaining.array[i]]); - if (F_status_is_error(status2) && status == F_none) { - status = status2; + if (F_status_is_error(status2) && setting->status == F_none) { + setting->status = status2; } } // for - funlockfile(main->output.to.stream); + f_file_stream_unlock(main->output.to); } } else { @@ -220,15 +107,15 @@ extern "C" { } if (main->parameters.remaining.used) { - flockfile(main->output.to.stream); + f_file_stream_lock(main->output.to); for (f_array_length_t i = 0; i < main->parameters.remaining.used; ++i) { if (!((++main->signal_check) % status_code_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - status_code_print_signal_received(main); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); - status = F_status_set_error(F_signal); + setting->status = F_status_set_error(F_signal); break; } @@ -236,26 +123,23 @@ extern "C" { main->signal_check = 0; } - status2 = status_code_process_normal(main, argv[main->parameters.remaining.array[i]]); + status2 = status_code_process_normal(main, setting, main->parameters.arguments.array[main->parameters.remaining.array[i]]); - if (F_status_is_error(status2) && status == F_none) { - status = status2; + if (F_status_is_error(status2) && setting->status == F_none) { + setting->status = status2; } } // for - funlockfile(main->output.to.stream); + f_file_stream_unlock(main->output.to); } } - if (F_status_set_fine(status) == F_interrupt) { - if (main->output.verbosity != f_console_verbosity_quiet_e) { - fflush(main->output.to.stream); - - fll_print_dynamic_raw(f_string_eol_s, main->output.to.stream); - } + if (F_status_is_error(setting->status)) { + status_code_print_line_last(setting, main->error, F_true); + } + else if (setting->status != F_interrupt) { + status_code_print_line_last(setting, main->message, F_true); } - - return status; } #endif // _di_status_code_main_ diff --git a/level_3/status_code/c/status_code.h b/level_3/status_code/c/status_code.h index a03e99b..d4fd0f2 100644 --- a/level_3/status_code/c/status_code.h +++ b/level_3/status_code/c/status_code.h @@ -43,27 +43,13 @@ // Status Code includes. #include +#include #ifdef __cplusplus extern "C" { #endif /** - * Print help. - * - * @param file - * The file to print to. - * @param context - * The color context settings. - * - * @return - * F_none on success. - */ -#ifndef _di_status_code_print_help_ - extern f_status_t status_code_print_help(const f_file_t file, const f_color_context_t context); -#endif // _di_status_code_print_help_ - -/** * Execute main program. * * If main.signal is non-zero, then this blocks and handles the following signals: @@ -76,16 +62,19 @@ extern "C" { * * @param main * The main program data. - * @param arguments - * The parameters passed to the process. + * @param setting + * The main program settings. * - * @return - * F_none on success. + * This alters setting.status: + * F_none on success. + * F_true on success when performing verification and verify passed. + * F_false on success when performing verification and verify failed. + * F_interrupt on (exit) signal received. * - * Status codes (with error bit) are returned on any problem. + * F_parameter (with error bit) if main is NULL or setting is NULL. */ #ifndef _di_status_code_main_ - extern f_status_t status_code_main(fll_program_data_t * const main, const f_console_arguments_t arguments); + extern void status_code_main(fll_program_data_t * const main, status_code_setting_t * const setting); #endif // _di_status_code_main_ #ifdef __cplusplus diff --git a/level_3/status_code/data/build/settings b/level_3/status_code/data/build/settings index 2c0d018..d4692cf 100644 --- a/level_3/status_code/data/build/settings +++ b/level_3/status_code/data/build/settings @@ -22,11 +22,11 @@ build_libraries-individual -lfll_error -lfll_print -lfll_program -lfll_status_st build_libraries-level -lfll_2 -lfll_1 -lfll_0 build_libraries-monolithic -lfll -build_sources_library status_code.c common.c private-common.c private-status_code.c +build_sources_library status_code.c common.c print.c private-common.c private-status_code.c build_sources_program main.c -build_sources_headers status_code.h common.h +build_sources_headers status_code.h common.h print.h build_script yes build_shared yes diff --git a/level_3/utf8/c/common.c b/level_3/utf8/c/common.c index e106a7d..1555f6b 100644 --- a/level_3/utf8/c/common.c +++ b/level_3/utf8/c/common.c @@ -74,6 +74,11 @@ extern "C" { #ifndef _di_utf8_setting_delete_ f_status_t utf8_setting_delete(utf8_setting_t * const setting) { + if (!setting) return F_status_set_error(F_parameter); + + f_string_dynamic_resize(0, &setting->buffer); + f_string_dynamic_resize(0, &setting->text); + f_string_dynamics_resize(0, &setting->path_files_from); f_string_dynamics_resize(0, &setting->path_files_to); @@ -84,6 +89,8 @@ extern "C" { #ifndef _di_utf8_setting_load_ void utf8_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, utf8_setting_t * const setting) { + if (!main || !setting) return; + // Load parameters. setting->status = f_console_parameter_process(arguments, &main->parameters); if (F_status_is_error(setting->status)) return; @@ -103,7 +110,9 @@ extern "C" { setting->status = fll_program_parameter_process_context(choices, modes, F_true, main); if (F_status_is_error(setting->status)) { + utf8_print_line_first(setting, main->error, F_true); fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_context", F_true); + utf8_print_line_last(setting, main->error, F_true); return; } @@ -134,7 +143,9 @@ extern "C" { setting->status = fll_program_parameter_process_verbosity(choices, verbosity, F_true, main); if (F_status_is_error(setting->status)) { + utf8_print_line_first(setting, main->error, F_true); fll_error_print(main->error, F_status_set_fine(setting->status), "fll_program_parameter_process_verbosity", F_true); + utf8_print_line_last(setting, main->error, F_true); return; } @@ -161,7 +172,9 @@ extern "C" { setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); if (F_status_is_error(setting->status)) { + utf8_print_line_first(setting, main->error, F_true); fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + utf8_print_line_last(setting, main->error, F_true); return; } @@ -192,7 +205,9 @@ extern "C" { setting->status = f_console_parameter_prioritize_right(main->parameters, choices, &choice); if (F_status_is_error(setting->status)) { + utf8_print_line_first(setting, main->error, F_true); fll_error_print(main->error, F_status_set_fine(setting->status), "f_console_parameter_prioritize_right", F_true); + utf8_print_line_last(setting, main->error, F_true); return; } @@ -410,8 +425,9 @@ extern "C" { #ifndef _di_utf8_setting_unload_ f_status_t utf8_setting_unload(fll_program_data_t * const main, utf8_setting_t * const setting) { - f_string_dynamic_resize(0, &setting->buffer); - f_string_dynamic_resize(0, &setting->text); + if (!main || !setting) return F_status_set_error(F_parameter); + + utf8_setting_delete(setting); return F_none; } diff --git a/level_3/utf8/c/common.h b/level_3/utf8/c/common.h index 66b5544..8fe8008 100644 --- a/level_3/utf8/c/common.h +++ b/level_3/utf8/c/common.h @@ -357,7 +357,7 @@ extern "C" { #endif // _di_utf8_main_flag_e_ /** - * The UTF-8 main program settings. + * The utf8 main program settings. * * This is passed to the program-specific main entry point to designate program settings. * These program settings are often processed from the program arguments (often called the command line arguments). @@ -430,10 +430,10 @@ extern "C" { * The program main setting data. * This does not alter setting.status. * - * Assumed to always be non-NULL. - * * @return * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. */ #ifndef _di_utf8_setting_delete_ extern f_status_t utf8_setting_delete(utf8_setting_t * const setting); @@ -444,17 +444,15 @@ extern "C" { * * This prints error messages as appropriate. * + * If either main or setting is NULL, then this immediately retuns without doing anything. + * * @param arguments * The parameters passed to the process (often referred to as command line arguments). * @param main * The main program data. - * - * Assumed to always be non-NULL. * @param setting * The main program settings. * - * Assumed to always be non-NULL. - * * This alters setting.status: * F_none on success. * @@ -473,17 +471,19 @@ extern "C" { * * @param main * The main program data. - * - * Assumed to always be non-NULL. * @param setting * The main program settings. * This does not alter setting.status. * All buffers are deallocated. * - * Assumed to always be non-NULL. - * * @return * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: utf8_setting_delete(). + * + * @see utf8_setting_delete() */ #ifndef _di_utf8_setting_unload_ extern f_status_t utf8_setting_unload(fll_program_data_t * const main, utf8_setting_t * const setting); diff --git a/level_3/utf8/c/main.c b/level_3/utf8/c/main.c index ae3f2f3..71e6c6d 100644 --- a/level_3/utf8/c/main.c +++ b/level_3/utf8/c/main.c @@ -26,11 +26,9 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) { utf8_setting_unload(&data, &setting); - utf8_setting_delete(&setting); - fll_program_data_delete(&data); fll_program_standard_set_down(&data); - return F_status_is_error(setting.status) || setting.status == F_false ? 1 : 0; + return (F_status_is_error(setting.status) || setting.status == F_false) ? 1 : 0; } diff --git a/level_3/utf8/c/print.c b/level_3/utf8/c/print.c index f00e616..5e87a36 100644 --- a/level_3/utf8/c/print.c +++ b/level_3/utf8/c/print.c @@ -169,7 +169,7 @@ extern "C" { if (main->error.verbosity == f_console_verbosity_quiet_e) return; - flockfile(main->error.to.stream); + f_file_stream_lock(main->error.to); utf8_print_line_first(setting, main->error, F_false); @@ -177,7 +177,7 @@ extern "C" { fl_print_format("%[%r%r%]", main->error.to.stream, main->context.set.notable, f_console_symbol_long_enable_s, parameter, main->context.set.notable); fl_print_format("%[' is specified, but no value was given.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); - funlockfile(main->error.to.stream); + f_file_stream_unlock(main->error.to); } #endif // _di_utf8_print_error_no_value_ @@ -186,7 +186,7 @@ extern "C" { if (main->error.verbosity == f_console_verbosity_quiet_e) return; - flockfile(main->error.to.stream); + f_file_stream_lock(main->error.to); utf8_print_line_first(setting, main->error, F_false); @@ -194,7 +194,7 @@ extern "C" { fl_print_format("%[%ul%]", main->error.to.stream, main->context.set.notable, index, main->context.set.notable); fl_print_format("%[.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); - funlockfile(main->error.to.stream); + f_file_stream_unlock(main->error.to); } #endif // _di_utf8_print_error_parameter_file_name_empty_ @@ -203,7 +203,7 @@ extern "C" { if (main->error.verbosity == f_console_verbosity_quiet_e) return; - flockfile(main->error.to.stream); + f_file_stream_lock(main->error.to); utf8_print_line_first(setting, main->error, F_false); @@ -211,7 +211,7 @@ extern "C" { fl_print_format("%[%Q%]", main->error.to.stream, main->context.set.notable, name, main->context.set.notable); fl_print_format("%['.%]%r", main->error.to.stream, main->context.set.error, main->context.set.error, f_string_eol_s); - funlockfile(main->error.to.stream); + f_file_stream_unlock(main->error.to); } #endif // _di_utf8_print_error_parameter_file_not_found_ @@ -246,54 +246,54 @@ extern "C" { #endif // _di_utf8_print_flush_ #ifndef _di_utf8_print_help_ - f_status_t utf8_print_help(utf8_setting_t * const setting, const f_file_t output, const f_color_context_t context) { + f_status_t utf8_print_help(utf8_setting_t * const setting, const fl_print_t print) { - flockfile(output.stream); + f_file_stream_lock(print.to); - f_print_dynamic_raw(setting->line_first, output.stream); + f_print_dynamic_raw(setting->line_first, print.to.stream); - fll_program_print_help_header(output, context, utf8_program_name_long_s, utf8_program_version_s); + fll_program_print_help_header(print, utf8_program_name_long_s, utf8_program_version_s); - fll_program_print_help_option_standard(output, context); + fll_program_print_help_option_standard(print); - f_print_dynamic_raw(f_string_eol_s, output.stream); + f_print_dynamic_raw(f_string_eol_s, print.to.stream); - fll_program_print_help_option(output, context, utf8_short_from_bytesequence_s, utf8_long_from_bytesequence_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The expected input format is byte sequence (character data)."); - fll_program_print_help_option(output, context, utf8_short_from_codepoint_s, utf8_long_from_codepoint_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The expected input format is codepoint (such as U+0000)."); - fll_program_print_help_option(output, context, utf8_short_from_file_s, utf8_long_from_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use the given output as the input source."); + fll_program_print_help_option(print, utf8_short_from_bytesequence_s, utf8_long_from_bytesequence_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The expected input format is byte sequence (character data)."); + fll_program_print_help_option(print, utf8_short_from_codepoint_s, utf8_long_from_codepoint_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The expected input format is codepoint (such as U+0000)."); + fll_program_print_help_option(print, utf8_short_from_file_s, utf8_long_from_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use the given print.to as the input source."); - f_print_dynamic_raw(f_string_eol_s, output.stream); + f_print_dynamic_raw(f_string_eol_s, print.to.stream); - fll_program_print_help_option(output, context, utf8_short_to_bytesequence_s, utf8_long_to_bytesequence_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The output format is byte sequence (character data)."); - fll_program_print_help_option(output, context, utf8_short_to_codepoint_s, utf8_long_to_codepoint_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The output format is codepoint (such as U+0000)."); - fll_program_print_help_option(output, context, utf8_short_to_combining_s, utf8_long_to_combining_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The output format is to print whether or not character is combining or not."); - fll_program_print_help_option(output, context, utf8_short_to_file_s, utf8_long_to_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use the given output as the output destination."); - fll_program_print_help_option(output, context, utf8_short_to_width_s, utf8_long_to_width_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The output format is to print the width of a character (either 0, 1, or 2)."); + fll_program_print_help_option(print, utf8_short_to_bytesequence_s, utf8_long_to_bytesequence_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "The print.to format is byte sequence (character data)."); + fll_program_print_help_option(print, utf8_short_to_codepoint_s, utf8_long_to_codepoint_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The print.to format is codepoint (such as U+0000)."); + fll_program_print_help_option(print, utf8_short_to_combining_s, utf8_long_to_combining_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The print.to format is to print whether or not character is combining or not."); + fll_program_print_help_option(print, utf8_short_to_file_s, utf8_long_to_file_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Use the given print.to as the print.to destination."); + fll_program_print_help_option(print, utf8_short_to_width_s, utf8_long_to_width_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " The print.to format is to print the width of a character (either 0, 1, or 2)."); - f_print_dynamic_raw(f_string_eol_s, output.stream); + f_print_dynamic_raw(f_string_eol_s, print.to.stream); - fll_program_print_help_option(output, context, utf8_short_headers_s, utf8_long_headers_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print headers for each section (pipe, output, or parameter)."); - fll_program_print_help_option(output, context, utf8_short_separate_s, utf8_long_separate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Separate characters by newlines (implied when printing headers)."); - fll_program_print_help_option(output, context, utf8_short_strip_invalid_s, utf8_long_strip_invalid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Strip invalid Unicode characters (do not print invalid sequences)."); - fll_program_print_help_option(output, context, utf8_short_verify_s, utf8_long_verify_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Only perform verification of valid sequences."); + fll_program_print_help_option(print, utf8_short_headers_s, utf8_long_headers_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Print headers for each section (pipe, file, or parameter)."); + fll_program_print_help_option(print, utf8_short_separate_s, utf8_long_separate_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Separate characters by newlines (implied when printing headers)."); + fll_program_print_help_option(print, utf8_short_strip_invalid_s, utf8_long_strip_invalid_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, "Strip invalid Unicode characters (do not print invalid sequences)."); + fll_program_print_help_option(print, utf8_short_verify_s, utf8_long_verify_s, f_console_symbol_short_enable_s, f_console_symbol_long_enable_s, " Only perform verification of valid sequences."); - fll_program_print_help_usage(output, context, utf8_program_name_s, utf8_program_help_parameters_s); + fll_program_print_help_usage(print, utf8_program_name_s, utf8_program_help_parameters_s); - fl_print_format("%r The default behavior is to assume the expected input is byte sequence from the command line to be output to the screen as codepoints.%r%r", output.stream, f_string_eol_s, f_string_eol_s, f_string_eol_s); + fl_print_format("%r The default behavior is to assume the expected input is byte sequence from the command line to be print.to to the screen as codepoints.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s, f_string_eol_s); - fl_print_format(" Multiple input sources are allowed but only a single output destination is allowed.%r%r", output.stream, f_string_eol_s, f_string_eol_s); + fl_print_format(" Multiple input sources are allowed but only a single print.to destination is allowed.%r%r", print.to.stream, f_string_eol_s, f_string_eol_s); - fl_print_format(" When using the parameter '%[%r%r%]', no data is printed and 0 is returned if valid or 1 is returned if invalid.%r%r", output.stream, context.set.notable, f_console_symbol_long_enable_s, utf8_long_verify_s, context.set.notable, f_string_eol_s, f_string_eol_s); + fl_print_format(" When using the parameter '%[%r%r%]', no data is printed and 0 is returned if valid or 1 is returned if invalid.%r%r", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, utf8_long_verify_s, print.set->notable, f_string_eol_s, f_string_eol_s); - fl_print_format(" When using the parameter '%[%r%r%]' with the parameter ", output.stream, context.set.notable, f_console_symbol_long_enable_s, utf8_long_to_combining_s, context.set.notable); - fl_print_format("'%[%r%r%]', the ", output.stream, context.set.notable, f_console_symbol_long_enable_s, utf8_long_to_width_s, context.set.notable); - fl_print_format("'%[%r%]' character is printed to represent the combining and the digits are used to represent widths.%r", output.stream, context.set.notable, utf8_string_combining_is_s, context.set.notable, f_string_eol_s); - fl_print_format(" The combining characters should be considered 1-width by themselves or 0-width when combined.%r", output.stream, f_string_eol_s); + fl_print_format(" When using the parameter '%[%r%r%]' with the parameter ", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, utf8_long_to_combining_s, print.set->notable); + fl_print_format("'%[%r%r%]', the ", print.to.stream, print.set->notable, f_console_symbol_long_enable_s, utf8_long_to_width_s, print.set->notable); + fl_print_format("'%[%r%]' character is printed to represent the combining and the digits are used to represent widths.%r", print.to.stream, print.set->notable, utf8_string_combining_is_s, print.set->notable, f_string_eol_s); + fl_print_format(" The combining characters should be considered 1-width by themselves or 0-width when combined.%r", print.to.stream, f_string_eol_s); - f_print_dynamic_raw(setting->line_last, output.stream); + f_print_dynamic_raw(setting->line_last, print.to.stream); - f_file_stream_flush(output); - funlockfile(output.stream); + f_file_stream_flush(print.to); + f_file_stream_unlock(print.to); return F_none; } @@ -487,30 +487,6 @@ extern "C" { } #endif // _di_utf8_print_section_header_pipe_ -#ifndef _di_utf8_print_signal_received_ - void utf8_print_signal_received(fll_program_data_t * const main, utf8_setting_t * const setting, const f_status_t signal) { - - if (main->warning.verbosity != f_console_verbosity_verbose_e && main->warning.verbosity != f_console_verbosity_debug_e) { - return; - } - - flockfile(main->warning.to.stream); - - // Must flush and reset color because the interrupt may have interrupted the middle of a print function. - f_file_stream_flush(main->warning.to); - - fl_print_format("%]", main->warning.to.stream, main->context.set.reset); - - utf8_print_line_first(setting, main->warning, F_false); - - fl_print_format("%r%[Received signal code %]", main->warning.to.stream, f_string_eol_s, main->context.set.warning, main->context.set.warning); - fl_print_format("%[%i%]", main->warning.to.stream, main->context.set.notable, signal, main->context.set.notable); - fl_print_format("%[.%]%r", main->warning.to.stream, main->context.set.warning, main->context.set.warning, f_string_eol_s); - - funlockfile(main->warning.to.stream); - } -#endif // _di_utf8_print_signal_received_ - #ifndef _di_utf8_print_width_ void utf8_print_width(fll_program_data_t * const main, utf8_setting_t * const setting, const f_string_static_t sequence) { diff --git a/level_3/utf8/c/print.h b/level_3/utf8/c/print.h index 21da76c..c02b5e3 100644 --- a/level_3/utf8/c/print.h +++ b/level_3/utf8/c/print.h @@ -229,18 +229,14 @@ extern "C" { * @param setting * The main program settings. * This does not alter setting.status. - * @param output - * The file to print to. - * @param context - * The color context settings. + * @param print + * The output structure to print to. * * @return * F_none on success. - * F_true on success and validation passed. - * F_false on success and validation failed. */ #ifndef _di_utf8_print_help_ - extern f_status_t utf8_print_help(utf8_setting_t * const setting, const f_file_t output, const f_color_context_t context); + extern f_status_t utf8_print_help(utf8_setting_t * const setting, const fl_print_t print); #endif // _di_utf8_print_help_ /** @@ -252,7 +248,7 @@ extern "C" { * The main program settings. * This does not alter setting.status. * @param print - * Designates how the how and where to print. + * Designates the how and where to print. * @param lock * If TRUE, then lock the stream. * If FALSE, then do not lock or unlock the stream. @@ -270,7 +266,7 @@ extern "C" { * The main program settings. * This does not alter setting.status. * @param print - * Designates how the how and where to print. + * Designates the how and where to print. * @param lock * If TRUE, then lock the stream. * If FALSE, then do not lock or unlock the stream. @@ -380,22 +376,6 @@ extern "C" { #endif // _di_utf8_print_section_header_pipe_ /** - * Print a message about a process signal being recieved, such as an interrupt signal. - * - * @param main - * The main program data. - * @param setting - * The main program settings. - * - * Assumed to always be non-NULL. - * @param signal - * The signal code received. - */ -#ifndef _di_utf8_print_signal_received_ - extern void utf8_print_signal_received(fll_program_data_t * const main, utf8_setting_t * const setting, const f_status_t signal); -#endif // _di_utf8_print_signal_received_ - -/** * Print the width of the given character. * * @param main diff --git a/level_3/utf8/c/private-utf8.c b/level_3/utf8/c/private-utf8.c index d7fbb0d..f62a891 100644 --- a/level_3/utf8/c/private-utf8.c +++ b/level_3/utf8/c/private-utf8.c @@ -25,7 +25,7 @@ extern "C" { if (!((++main->signal_check) % utf8_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - utf8_print_signal_received(main, setting, status); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_status_set_error(F_interrupt); diff --git a/level_3/utf8/c/private-utf8_bytesequence.c b/level_3/utf8/c/private-utf8_bytesequence.c index 6f454ce..fd55550 100644 --- a/level_3/utf8/c/private-utf8_bytesequence.c +++ b/level_3/utf8/c/private-utf8_bytesequence.c @@ -81,7 +81,7 @@ extern "C" { if (!((++main->signal_check) % utf8_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - utf8_print_signal_received(main, setting, status); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_interrupt; diff --git a/level_3/utf8/c/private-utf8_codepoint.c b/level_3/utf8/c/private-utf8_codepoint.c index ddf0956..29cc930 100644 --- a/level_3/utf8/c/private-utf8_codepoint.c +++ b/level_3/utf8/c/private-utf8_codepoint.c @@ -354,7 +354,7 @@ extern "C" { if (!((++main->signal_check) % utf8_signal_check_d)) { if (fll_program_standard_signal_received(main)) { - utf8_print_signal_received(main, setting, status); + fll_program_print_signal_received(main->warning, setting->line_first, main->signal_received); status = F_interrupt; diff --git a/level_3/utf8/c/utf8.c b/level_3/utf8/c/utf8.c index ad93cae..9dfc146 100644 --- a/level_3/utf8/c/utf8.c +++ b/level_3/utf8/c/utf8.c @@ -16,25 +16,23 @@ extern "C" { fll_error_print(main->error, F_parameter, "utf8_main", F_true); utf8_print_line_last(setting, main->error, F_true); - return; - } - - if (F_status_is_error(setting->status)) { - utf8_print_line_last(setting, main->error, F_true); + setting->status = F_status_set_error(F_parameter); return; } + if (F_status_is_error(setting->status)) return; + setting->status = F_none; if (setting->flag & utf8_main_flag_help_e) { - utf8_print_help(setting, main->message.to, main->context); + utf8_print_help(setting, main->message); return; } if (setting->flag & utf8_main_flag_version_e) { - fll_program_print_version(main->message.to, utf8_program_version_s); + fll_program_print_version(main->message, utf8_program_version_s); return; }