From: Kevin Day Date: Mon, 22 Aug 2022 23:11:19 +0000 (-0500) Subject: Progress: Continue program related work. X-Git-Tag: 0.7.0~866 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 fd4c97f15..43150751d 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 6d66025d5..39869bc57 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 1c032a807..d2142d221 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 c17666961..e842f15a1 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 949ccf691..37c985050 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" { @@ -2051,459 +2048,6 @@ extern "C" { extern f_status_t f_file_stat_by_id(const f_file_t file, struct stat * const stat_file); #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. * diff --git a/level_0/f_file/c/file/common.h b/level_0/f_file/c/file/common.h index b7f197f4c..b1883fec1 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 000000000..593841225 --- /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 000000000..a5b3fc0e1 --- /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 5e7561e54..0ed2726f3 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 d467aacf9..33eb42981 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 d6d3b5989..9e9cc5b05 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 2b897fad3..0e5cb973a 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 20d64578a..11b626009 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 b8199dd39..56bea80a0 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 80f7e62fc..9e1064d61 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 2971f6974..72c2fe931 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 79c86da45..b433bfb39 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 7ba650fc2..d3afb00ee 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 22a71cee1..ccda4f8e8 100644 --- a/level_2/fll_program/c/program.h +++ b/level_2/fll_program/c/program.h @@ -31,180 +31,12 @@ // 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. * @@ -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 000000000..285cebb92 --- /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 000000000..7568fb9ac --- /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 76dcafb25..081fa82ae 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 529a76a80..d23bbd3a4 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 bbeb216b0..f23e81163 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 f25b91a73..893b430a1 100644 --- a/level_3/byte_dump/c/byte_dump.h +++ b/level_3/byte_dump/c/byte_dump.h @@ -53,23 +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. - * - * @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. * @@ -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 a9659c7dd..53e56aa2e 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 17e88a91c..df5c7ec53 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 f05e1b093..d32ca7f7f 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 000000000..da007dae3 --- /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 000000000..311a6a3ac --- /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 2d94f9691..d72dac895 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 54d8b2166..820be9031 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 de72becb9..12c01cbe9 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 348b33894..ce543f92d 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 846c3d57d..550fde8b9 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 1e77a7d65..3712dfe74 100644 --- a/level_3/control/c/common.h +++ b/level_3/control/c/common.h @@ -187,6 +187,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. * @@ -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 91c9c2102..4c2864b2a 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 a1f387d89..980be6c9c 100644 --- a/level_3/control/c/control.h +++ b/level_3/control/c/control.h @@ -57,21 +57,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. * @@ -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 4c909ac2f..910a490b6 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 000000000..66872e572 --- /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 000000000..d0fbdea9c --- /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 4963f400c..8fdfaefa6 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 3241e2e46..d136ec124 100644 --- a/level_3/control/c/private-print.h +++ b/level_3/control/c/private-print.h @@ -308,18 +308,6 @@ extern "C" { extern void control_print_error_socket_file_not(const fll_program_data_t * const main, const f_string_static_t path_socket) F_attribute_visibility_internal_d; #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). * diff --git a/level_3/control/data/build/settings b/level_3/control/data/build/settings index 39ea2d1bd..f5f42a5fc 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 3d4d10216..c73b69310 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 be9d88c44..bd62ff94f 100644 --- a/level_3/controller/c/common.h +++ b/level_3/controller/c/common.h @@ -445,6 +445,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. * @@ -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 8c3daf3fd..595d63f42 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 3e3e0322a..d3ae9b568 100644 --- a/level_3/controller/c/controller.h +++ b/level_3/controller/c/controller.h @@ -81,21 +81,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. * diff --git a/level_3/controller/c/controller/private-controller_print.c b/level_3/controller/c/controller/private-controller_print.c index 230c99ed8..863c3a311 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 451ac21e4..ffce643c8 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 5613eece6..0d53d9e81 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 39d9cda8d..9a8123514 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 000000000..4e41cd3d3 --- /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 000000000..c791d966d --- /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 d5b401a37..b44898812 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 299a0b2f6..4e0a994d7 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 7565db196..9f06812f4 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 3dc0044c2..46ec2b04a 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 273d14652..002dcf6c9 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 7c7a32640..972d3268a 100644 --- a/level_3/fake/c/fake.h +++ b/level_3/fake/c/fake.h @@ -96,21 +96,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. * @@ -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 75db8a37c..1a1da04d4 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 000000000..ab6653055 --- /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 000000000..4f10ebda5 --- /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 51c0707f0..3faf7487c 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 df4bc55b1..99f1d16f6 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 a847f01bd..fd5bd8f50 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 26e3372e4..d63b29ce5 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 d869d4df9..501f3da33 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 941910c76..80f271490 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 d2d06f309..621322663 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 43381f7fa..02ba75e75 100644 --- a/level_3/fake/c/private-print.h +++ b/level_3/fake/c/private-print.h @@ -351,21 +351,6 @@ extern "C" { extern void fake_print_message_section_operation_unknown(fake_data_t * const data, const fl_print_t print, const f_string_static_t buffer, const f_string_range_t section_name, const f_string_range_t operation_name) F_attribute_visibility_internal_d; #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. * diff --git a/level_3/fake/data/build/settings b/level_3/fake/data/build/settings index f776a894b..9c80dfc60 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 2a64521bc..e921ce912 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 410a4bc30..b6893ed04 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 7bb364e37..ca0f6303d 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 37032a5f9..b05ec3ca2 100644 --- a/level_3/firewall/c/firewall.h +++ b/level_3/firewall/c/firewall.h @@ -54,21 +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. - */ -#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. * @@ -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 6a931ef8d..09a0c725b 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 000000000..7c2eaea93 --- /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 000000000..f7ff2c4b1 --- /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 dadb9e240..d20e7567f 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 461cb908d..b2c3b41b5 100644 --- a/level_3/firewall/c/private-common.h +++ b/level_3/firewall/c/private-common.h @@ -188,18 +188,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. * diff --git a/level_3/firewall/data/build/settings b/level_3/firewall/data/build/settings index 223d86788..4da5bf3e2 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 a31922b93..63fb628da 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 d5b5285e7..e2aca2713 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 53f2c8eeb..1abbed337 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 857aca433..d6bc982b7 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 @@ -54,21 +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. - */ -#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. * @@ -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 eac022416..f4f6dbcf5 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 000000000..c74adf8c2 --- /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 000000000..d75c2f30f --- /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 7f1e7e850..a1861b3b5 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 75cd604c0..7e94adbb2 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 d327877c4..74c033351 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 1bd191974..66d740ece 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 87f363eae..b3b13296b 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 3a7985b26..671256378 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 3c233d0a6..311fb52c7 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 7e896fcc3..251c71942 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 @@ -46,21 +46,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. * @@ -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 180951474..fd6a53bdb 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 000000000..10b365922 --- /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 000000000..12ddbc0b7 --- /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 d62960d64..197549192 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 b4be76a92..13524a4c7 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 62ee9dd57..4d3d125e8 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 2168e1469..f92a44890 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 b9c097ab2..923d37c07 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 33b2f0169..d02c6fd99 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 71a178b30..5aee79cf9 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 aac0e6b78..acc481f09 100644 --- a/level_3/fss_basic_read/c/fss_basic_read.h +++ b/level_3/fss_basic_read/c/fss_basic_read.h @@ -54,21 +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. - */ -#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. * @@ -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 ddd18479b..33b3e5880 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 000000000..13fd2b320 --- /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 000000000..ae20be3e2 --- /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 d89a23acc..0bfe45481 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 e942aca65..4f8b126a6 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 28760fc89..657a5d4e0 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 081696b9a..f78b28207 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 f417c1f47..4e4edf15a 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 c0764f4d0..165487339 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 448fdd610..b375bb6ba 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 21d11c969..f9b32946a 100644 --- a/level_3/fss_basic_write/c/fss_basic_write.h +++ b/level_3/fss_basic_write/c/fss_basic_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_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. * @@ -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 0c1a9a5bd..c953bc546 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 000000000..9cd5a0088 --- /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 000000000..99ef64993 --- /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 f3fb15e1b..d1c0ac4f2 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 972ecdc7c..c9af8243b 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 9c5c7f3e3..d86cd5fef 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 12f063769..292c290af 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 d93b633fc..98a5025d7 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 70f025ad4..bf6257043 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 3eb1dba03..e8d476249 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 f6e853d6c..01450670f 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 @@ -54,21 +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. - */ -#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. * @@ -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 fa84dae30..db1288bc6 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 000000000..131192460 --- /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 000000000..478754118 --- /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 f11d776ba..ddc05e235 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 30ef1431a..b673ccc6d 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 c013d58b1..3bf2ca371 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 d00cd4677..ef09d6be0 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 9a528ee65..a31b4b71c 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 6351e6511..2e0c4c89c 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 ddfb5f1d5..a5bd5327c 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 23002ef00..4347d39ca 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 @@ -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_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. * @@ -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 bd708bdb8..501e05252 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 000000000..bddc7b73f --- /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 000000000..562dfed38 --- /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 656ffaebc..16c4cbb6d 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 569d3ecba..85df5d008 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 252624162..3654add0d 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 ee5cdf493..2359e055d 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 e7fedce0d..1726e8f09 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 59b7d8e72..7360cbf09 100644 --- a/level_3/fss_extended_list_read/c/common.h +++ b/level_3/fss_extended_list_read/c/common.h @@ -293,6 +293,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. * @@ -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 9981c3967..218d78ca0 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 847c84596..b2b6cc5fd 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 @@ -54,21 +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. - */ -#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. * @@ -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 30e46c990..aff8ca90e 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 000000000..893c762c0 --- /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 000000000..73015d030 --- /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 688b59e0f..46fcfa1fb 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 0dc07c416..8bd3c494d 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 1da5a70d7..3494f4bcc 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 683d0db2f..c67a02ad3 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 4adc3bbff..ec3991a21 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 b80105eba..2699c8229 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 a82340b2f..4b3c9a67c 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 ce18f5b60..64f3df75f 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 @@ -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_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. * @@ -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 6814f7d92..40848bee7 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 000000000..0b44a87b3 --- /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 000000000..9da45b4ce --- /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 24de2602d..4e3d529db 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 891a2ab43..08cc0999c 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 47e754f7b..1a44c8d99 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 c8ca91170..4d34c0ec6 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 0f44d4354..cb20d4340 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 e4a38b608..76f31677d 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 4226bb8ca..b64bbfae2 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 bbdd1bf07..9d28801cc 100644 --- a/level_3/fss_extended_read/c/fss_extended_read.h +++ b/level_3/fss_extended_read/c/fss_extended_read.h @@ -54,21 +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. - */ -#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. * @@ -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 95d7a453c..5998ee615 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 000000000..c9f770a34 --- /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 000000000..7d543dc18 --- /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 9c7dcb157..ac6911f4a 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 cbbe68501..a25d20151 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 d4f79509f..fedaa0ed2 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 7b6720a89..42d9f1c9a 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 12ecb7265..f4323601f 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 3ba6427db..03ba6d0f0 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 9ecf12e97..de6d4b9a2 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 b444dfd30..e1da061a5 100644 --- a/level_3/fss_extended_write/c/fss_extended_write.h +++ b/level_3/fss_extended_write/c/fss_extended_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_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. * @@ -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 48d1286f8..c6cc6f3c0 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 000000000..9e5e72f35 --- /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 000000000..79dffc537 --- /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 2d5b189af..635db9c18 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 a1f81794d..d7617beb1 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 a33d943a3..c1cdbe450 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 151ed4004..22315b9fe 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 2ab2fa7e0..2e87b1848 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 38764dd3a..8fa4c91fd 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 f42a1ffdf..f5a071135 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 501d1576b..a7750e6e7 100644 --- a/level_3/fss_identify/c/fss_identify.h +++ b/level_3/fss_identify/c/fss_identify.h @@ -52,21 +52,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. * @@ -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 1b697b802..5ef29a147 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 000000000..36e102b51 --- /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 000000000..437e9825a --- /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 3d7aba08a..e6d4b34c0 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 e584f3676..72491fa5b 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 0441ddb80..2fa7c040d 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 a016bd40f..9797c7cdb 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 0c742fad0..49fdb5d55 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 186be3c4b..839adb7ba 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 01cfa0cf0..4b536ae33 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 1aaca7ea4..237c49c1a 100644 --- a/level_3/fss_payload_read/c/fss_payload_read.h +++ b/level_3/fss_payload_read/c/fss_payload_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_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. * @@ -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 c4e4387a7..1fa6db4cd 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 000000000..5bb495178 --- /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 000000000..5b441162a --- /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 7816a6dc4..7ba318340 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 c19e859d7..e52f23459 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 36e0da4e4..d99d35d7d 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 cb89eb06f..94ca06f48 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 6d321da50..84a5dcfd4 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 5f8126f95..b9094ebbd 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 1cc34ec24..0669bb8cb 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 da56d8166..1f640190c 100644 --- a/level_3/fss_payload_write/c/fss_payload_write.h +++ b/level_3/fss_payload_write/c/fss_payload_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_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. * @@ -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 5a9452cf1..e9649899d 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 000000000..91f5ca5c4 --- /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 000000000..b2fb19a36 --- /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 87bff8596..33626b57d 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 51b200164..126294685 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 964cc9bfa..3b93b2abf 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 84c0b5ae1..e661405dd 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 c6e73aaf8..0d5f5481b 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 5f531b766..690917fb4 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 * @@ -69,6 +69,35 @@ extern "C" { extern const f_string_static_t fss_status_code_program_help_parameters_s; #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. */ @@ -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 c84f07c1c..3b580e4f6 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 be8a2ce41..e3458dd71 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,26 +44,12 @@ // 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. * @@ -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 3cff8f689..1f56485d2 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 000000000..f0d58a242 --- /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 000000000..cca7957d5 --- /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 ed96d23a1..24a88a74b 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 7e8029c47..53a416ea1 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 7ee3d6c49..77147b8b6 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 182c93d3c..56a600b9a 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 703e58072..f223e8958 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 00af88241..a0ccf6097 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 945aa8bd8..70f25e092 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 927eea770..3b03fb6cf 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 79d0f5f38..d26c134eb 100644 --- a/level_3/iki_read/c/iki_read.h +++ b/level_3/iki_read/c/iki_read.h @@ -57,21 +57,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. * @@ -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 56ed1be02..87d88e417 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 000000000..e901ed135 --- /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 000000000..9afe97855 --- /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 3173b73f4..6d208abcf 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 471afccb4..3039b9a4e 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 1848ff64a..c4f81a26e 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 4c8ec6aae..99332ffd7 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 79b2b32d0..3f91b7f00 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 84a2dd07b..f41b1df5c 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 f3e93fd09..b73418632 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 95d8b8843..993dc44dd 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 c2562cecf..0da4da3cc 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 2497a3cb5..c265da3ab 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 58fab705b..325155061 100644 --- a/level_3/iki_write/c/iki_write.h +++ b/level_3/iki_write/c/iki_write.h @@ -57,21 +57,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. * @@ -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 f6b68d1fd..fa672df4d 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 000000000..024918776 --- /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 000000000..7d27db151 --- /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 5168e724c..a14b2d907 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 5ec92d616..54c09450d 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 0cc2b77dd..8e5db8f38 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 a778a1885..1743b9b88 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 4f280213e..801023a31 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 abccb6dcf..f6466066b 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 1d77a4b79..30305319b 100644 --- a/level_3/status_code/c/common.h +++ b/level_3/status_code/c/common.h @@ -69,6 +69,35 @@ extern "C" { extern const f_string_static_t status_code_program_help_parameters_s; #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. */ @@ -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 98802168b..5c7ac19ff 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 000000000..d28b8b1e3 --- /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 000000000..e54106233 --- /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 1ee3c476b..7540b79d0 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 6a1589dff..dc1d6a4e2 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 5054717d9..24684d3f2 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 acfa72cc7..889ea70e8 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 620d0e8d3..94fe552f8 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 a03e99bd3..d4fd0f2eb 100644 --- a/level_3/status_code/c/status_code.h +++ b/level_3/status_code/c/status_code.h @@ -43,26 +43,12 @@ // 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. * @@ -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 2c0d018c0..d4692cff5 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 e106a7d38..1555f6bd7 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 66b55448a..8fe80085f 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 ae3f2f32c..71e6c6d07 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 f00e61693..5e87a3641 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 21da76cd8..c02b5e3f8 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. @@ -379,22 +375,6 @@ extern "C" { extern void utf8_print_section_header_pipe(fll_program_data_t * const main, utf8_setting_t * const setting); #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. * diff --git a/level_3/utf8/c/private-utf8.c b/level_3/utf8/c/private-utf8.c index d7fbb0d3b..f62a891eb 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 6f454ce89..fd5555048 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 ddf0956d2..29cc93014 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 ad93caeb5..9dfc146bd 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; }