]> Kevux Git Server - fll/commitdiff
Progress: Continue program related work.
authorKevin Day <thekevinday@gmail.com>
Mon, 22 Aug 2022 23:11:19 +0000 (18:11 -0500)
committerKevin Day <thekevinday@gmail.com>
Wed, 24 Aug 2022 03:46:13 +0000 (22:46 -0500)
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).

284 files changed:
build/level_0/settings
build/level_2/settings
build/monolithic/settings
level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_0/f_file/c/file/common.h
level_0/f_file/c/file/stream.c [new file with mode: 0644]
level_0/f_file/c/file/stream.h [new file with mode: 0644]
level_0/f_file/data/build/settings
level_0/f_file/data/build/settings-mocks
level_0/f_memory/c/memory.c
level_0/f_status/c/status.h
level_0/f_status_string/c/status_string.c
level_0/f_status_string/c/status_string.h
level_0/f_status_string/tests/unit/c/test-status_string-to.c
level_2/fll_program/c/private-program.c
level_2/fll_program/c/private-program.h
level_2/fll_program/c/program.c
level_2/fll_program/c/program.h
level_2/fll_program/c/program/print.c [new file with mode: 0644]
level_2/fll_program/c/program/print.h [new file with mode: 0644]
level_2/fll_program/data/build/settings
level_2/fll_status_string/tests/unit/c/test-status_string-from.c
level_3/byte_dump/c/byte_dump.c
level_3/byte_dump/c/byte_dump.h
level_3/byte_dump/c/common.c
level_3/byte_dump/c/common.h
level_3/byte_dump/c/main.c
level_3/byte_dump/c/print.c [new file with mode: 0644]
level_3/byte_dump/c/print.h [new file with mode: 0644]
level_3/byte_dump/c/private-byte_dump.c
level_3/byte_dump/c/private-common.c
level_3/byte_dump/c/private-common.h
level_3/byte_dump/data/build/settings
level_3/control/c/common.c
level_3/control/c/common.h
level_3/control/c/control.c
level_3/control/c/control.h
level_3/control/c/main.c
level_3/control/c/print.c [new file with mode: 0644]
level_3/control/c/print.h [new file with mode: 0644]
level_3/control/c/private-print.c
level_3/control/c/private-print.h
level_3/control/data/build/settings
level_3/controller/c/common.c
level_3/controller/c/common.h
level_3/controller/c/controller.c
level_3/controller/c/controller.h
level_3/controller/c/controller/private-controller_print.c
level_3/controller/c/controller/private-controller_print.h
level_3/controller/c/lock/private-lock_print.c
level_3/controller/c/main.c
level_3/controller/c/print.c [new file with mode: 0644]
level_3/controller/c/print.h [new file with mode: 0644]
level_3/controller/c/thread/private-thread.c
level_3/controller/data/build/settings
level_3/fake/c/common.c
level_3/fake/c/common.h
level_3/fake/c/fake.c
level_3/fake/c/fake.h
level_3/fake/c/main.c
level_3/fake/c/print.c [new file with mode: 0644]
level_3/fake/c/print.h [new file with mode: 0644]
level_3/fake/c/private-build-load.c
level_3/fake/c/private-build.c
level_3/fake/c/private-fake.c
level_3/fake/c/private-make-load_fakefile.c
level_3/fake/c/private-make-operate.c
level_3/fake/c/private-make-operate_process.c
level_3/fake/c/private-print.c
level_3/fake/c/private-print.h
level_3/fake/data/build/settings
level_3/firewall/c/common.c
level_3/firewall/c/common.h
level_3/firewall/c/firewall.c
level_3/firewall/c/firewall.h
level_3/firewall/c/main.c
level_3/firewall/c/print.c [new file with mode: 0644]
level_3/firewall/c/print.h [new file with mode: 0644]
level_3/firewall/c/private-common.c
level_3/firewall/c/private-common.h
level_3/firewall/data/build/settings
level_3/fss_basic_list_read/c/common.c
level_3/fss_basic_list_read/c/common.h
level_3/fss_basic_list_read/c/fss_basic_list_read.c
level_3/fss_basic_list_read/c/fss_basic_list_read.h
level_3/fss_basic_list_read/c/main.c
level_3/fss_basic_list_read/c/print.c [new file with mode: 0644]
level_3/fss_basic_list_read/c/print.h [new file with mode: 0644]
level_3/fss_basic_list_read/c/private-common.c
level_3/fss_basic_list_read/c/private-common.h
level_3/fss_basic_list_read/c/private-read.c
level_3/fss_basic_list_read/data/build/settings
level_3/fss_basic_list_write/c/common.c
level_3/fss_basic_list_write/c/common.h
level_3/fss_basic_list_write/c/fss_basic_list_write.c
level_3/fss_basic_list_write/c/fss_basic_list_write.h
level_3/fss_basic_list_write/c/main.c
level_3/fss_basic_list_write/c/print.c [new file with mode: 0644]
level_3/fss_basic_list_write/c/print.h [new file with mode: 0644]
level_3/fss_basic_list_write/c/private-common.c
level_3/fss_basic_list_write/c/private-common.h
level_3/fss_basic_list_write/c/private-write.c
level_3/fss_basic_list_write/data/build/settings
level_3/fss_basic_read/c/common.c
level_3/fss_basic_read/c/common.h
level_3/fss_basic_read/c/fss_basic_read.c
level_3/fss_basic_read/c/fss_basic_read.h
level_3/fss_basic_read/c/main.c
level_3/fss_basic_read/c/print.c [new file with mode: 0644]
level_3/fss_basic_read/c/print.h [new file with mode: 0644]
level_3/fss_basic_read/c/private-common.c
level_3/fss_basic_read/c/private-common.h
level_3/fss_basic_read/c/private-read.c
level_3/fss_basic_read/data/build/settings
level_3/fss_basic_write/c/common.c
level_3/fss_basic_write/c/common.h
level_3/fss_basic_write/c/fss_basic_write.c
level_3/fss_basic_write/c/fss_basic_write.h
level_3/fss_basic_write/c/main.c
level_3/fss_basic_write/c/print.c [new file with mode: 0644]
level_3/fss_basic_write/c/print.h [new file with mode: 0644]
level_3/fss_basic_write/c/private-common.c
level_3/fss_basic_write/c/private-common.h
level_3/fss_basic_write/c/private-write.c
level_3/fss_basic_write/data/build/settings
level_3/fss_embedded_list_read/c/common.c
level_3/fss_embedded_list_read/c/common.h
level_3/fss_embedded_list_read/c/fss_embedded_list_read.c
level_3/fss_embedded_list_read/c/fss_embedded_list_read.h
level_3/fss_embedded_list_read/c/main.c
level_3/fss_embedded_list_read/c/print.c [new file with mode: 0644]
level_3/fss_embedded_list_read/c/print.h [new file with mode: 0644]
level_3/fss_embedded_list_read/c/private-common.c
level_3/fss_embedded_list_read/c/private-common.h
level_3/fss_embedded_list_read/c/private-read.c
level_3/fss_embedded_list_read/data/build/settings
level_3/fss_embedded_list_write/c/common.c
level_3/fss_embedded_list_write/c/common.h
level_3/fss_embedded_list_write/c/fss_embedded_list_write.c
level_3/fss_embedded_list_write/c/fss_embedded_list_write.h
level_3/fss_embedded_list_write/c/main.c
level_3/fss_embedded_list_write/c/print.c [new file with mode: 0644]
level_3/fss_embedded_list_write/c/print.h [new file with mode: 0644]
level_3/fss_embedded_list_write/c/private-common.c
level_3/fss_embedded_list_write/c/private-common.h
level_3/fss_embedded_list_write/c/private-write.c
level_3/fss_embedded_list_write/data/build/settings
level_3/fss_extended_list_read/c/common.c
level_3/fss_extended_list_read/c/common.h
level_3/fss_extended_list_read/c/fss_extended_list_read.c
level_3/fss_extended_list_read/c/fss_extended_list_read.h
level_3/fss_extended_list_read/c/main.c
level_3/fss_extended_list_read/c/print.c [new file with mode: 0644]
level_3/fss_extended_list_read/c/print.h [new file with mode: 0644]
level_3/fss_extended_list_read/c/private-common.c
level_3/fss_extended_list_read/c/private-common.h
level_3/fss_extended_list_read/c/private-read.c
level_3/fss_extended_list_read/data/build/settings
level_3/fss_extended_list_write/c/common.c
level_3/fss_extended_list_write/c/common.h
level_3/fss_extended_list_write/c/fss_extended_list_write.c
level_3/fss_extended_list_write/c/fss_extended_list_write.h
level_3/fss_extended_list_write/c/main.c
level_3/fss_extended_list_write/c/print.c [new file with mode: 0644]
level_3/fss_extended_list_write/c/print.h [new file with mode: 0644]
level_3/fss_extended_list_write/c/private-common.c
level_3/fss_extended_list_write/c/private-common.h
level_3/fss_extended_list_write/c/private-write.c
level_3/fss_extended_list_write/data/build/settings
level_3/fss_extended_read/c/common.c
level_3/fss_extended_read/c/common.h
level_3/fss_extended_read/c/fss_extended_read.c
level_3/fss_extended_read/c/fss_extended_read.h
level_3/fss_extended_read/c/main.c
level_3/fss_extended_read/c/print.c [new file with mode: 0644]
level_3/fss_extended_read/c/print.h [new file with mode: 0644]
level_3/fss_extended_read/c/private-common.c
level_3/fss_extended_read/c/private-common.h
level_3/fss_extended_read/c/private-read.c
level_3/fss_extended_read/data/build/settings
level_3/fss_extended_write/c/common.c
level_3/fss_extended_write/c/common.h
level_3/fss_extended_write/c/fss_extended_write.c
level_3/fss_extended_write/c/fss_extended_write.h
level_3/fss_extended_write/c/main.c
level_3/fss_extended_write/c/print.c [new file with mode: 0644]
level_3/fss_extended_write/c/print.h [new file with mode: 0644]
level_3/fss_extended_write/c/private-common.c
level_3/fss_extended_write/c/private-common.h
level_3/fss_extended_write/c/private-write.c
level_3/fss_extended_write/data/build/settings
level_3/fss_identify/c/common.c
level_3/fss_identify/c/common.h
level_3/fss_identify/c/fss_identify.c
level_3/fss_identify/c/fss_identify.h
level_3/fss_identify/c/main.c
level_3/fss_identify/c/print.c [new file with mode: 0644]
level_3/fss_identify/c/print.h [new file with mode: 0644]
level_3/fss_identify/c/private-common.c
level_3/fss_identify/c/private-common.h
level_3/fss_identify/c/private-identify.c
level_3/fss_identify/data/build/settings
level_3/fss_payload_read/c/common.c
level_3/fss_payload_read/c/common.h
level_3/fss_payload_read/c/fss_payload_read.c
level_3/fss_payload_read/c/fss_payload_read.h
level_3/fss_payload_read/c/main.c
level_3/fss_payload_read/c/print.c [new file with mode: 0644]
level_3/fss_payload_read/c/print.h [new file with mode: 0644]
level_3/fss_payload_read/c/private-common.c
level_3/fss_payload_read/c/private-common.h
level_3/fss_payload_read/c/private-read.c
level_3/fss_payload_read/data/build/settings
level_3/fss_payload_write/c/common.c
level_3/fss_payload_write/c/common.h
level_3/fss_payload_write/c/fss_payload_write.c
level_3/fss_payload_write/c/fss_payload_write.h
level_3/fss_payload_write/c/main.c
level_3/fss_payload_write/c/print.c [new file with mode: 0644]
level_3/fss_payload_write/c/print.h [new file with mode: 0644]
level_3/fss_payload_write/c/private-common.c
level_3/fss_payload_write/c/private-common.h
level_3/fss_payload_write/c/private-write.c
level_3/fss_payload_write/data/build/settings
level_3/fss_status_code/c/common.c
level_3/fss_status_code/c/common.h
level_3/fss_status_code/c/fss_status_code.c
level_3/fss_status_code/c/fss_status_code.h
level_3/fss_status_code/c/main.c
level_3/fss_status_code/c/print.c [new file with mode: 0644]
level_3/fss_status_code/c/print.h [new file with mode: 0644]
level_3/fss_status_code/c/private-common.c
level_3/fss_status_code/c/private-common.h
level_3/fss_status_code/c/private-fss_status_code.c
level_3/fss_status_code/c/private-fss_status_code.h
level_3/fss_status_code/data/build/settings
level_3/iki_read/c/common.c
level_3/iki_read/c/common.h
level_3/iki_read/c/iki_read.c
level_3/iki_read/c/iki_read.h
level_3/iki_read/c/main.c
level_3/iki_read/c/print.c [new file with mode: 0644]
level_3/iki_read/c/print.h [new file with mode: 0644]
level_3/iki_read/c/private-common.c
level_3/iki_read/c/private-common.h
level_3/iki_read/c/private-print.c
level_3/iki_read/c/private-print.h
level_3/iki_read/c/private-read.c
level_3/iki_read/c/private-read.h
level_3/iki_read/data/build/settings
level_3/iki_write/c/common.c
level_3/iki_write/c/common.h
level_3/iki_write/c/iki_write.c
level_3/iki_write/c/iki_write.h
level_3/iki_write/c/main.c
level_3/iki_write/c/print.c [new file with mode: 0644]
level_3/iki_write/c/print.h [new file with mode: 0644]
level_3/iki_write/c/private-common.c
level_3/iki_write/c/private-common.h
level_3/iki_write/c/private-write.c
level_3/iki_write/c/private-write.h
level_3/iki_write/data/build/settings
level_3/status_code/c/common.c
level_3/status_code/c/common.h
level_3/status_code/c/main.c
level_3/status_code/c/print.c [new file with mode: 0644]
level_3/status_code/c/print.h [new file with mode: 0644]
level_3/status_code/c/private-common.c
level_3/status_code/c/private-common.h
level_3/status_code/c/private-status_code.c
level_3/status_code/c/private-status_code.h
level_3/status_code/c/status_code.c
level_3/status_code/c/status_code.h
level_3/status_code/data/build/settings
level_3/utf8/c/common.c
level_3/utf8/c/common.h
level_3/utf8/c/main.c
level_3/utf8/c/print.c
level_3/utf8/c/print.h
level_3/utf8/c/private-utf8.c
level_3/utf8/c/private-utf8_bytesequence.c
level_3/utf8/c/private-utf8_codepoint.c
level_3/utf8/c/utf8.c

index fd4c97f15760e3315be90488f9c3377bed238c2a..43150751dc4af7dac15b32ead26cdafe516eff18 100644 (file)
@@ -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
index 6d66025d50fed84a8d7e1112a7bd21fc87b5b2e8..39869bc572aa8033979911acdaa18550e52b3666 100644 (file)
@@ -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
index 1c032a807cf152302af5e15c5846a2c205df5570..d2142d2218bd82018462f73c2d02f33f859dbff4 100644 (file)
@@ -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
index c17666961aedd7a9aa317990f935e68bbc0c3ac2..e842f15a1ccf3d72063c747c3044752bb7c4f6b2 100644 (file)
@@ -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) {
 
index 949ccf691c3c74abb8a49e3cf2939bab752bc227..37c98505005a09b0a6d462509a94a4628f2de3bd 100644 (file)
@@ -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 <fll/level_0/file/common.h>
+#include <fll/level_0/file/stream.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -2052,459 +2049,6 @@ extern "C" {
 #endif // _di_f_file_stat_by_id_
 
 /**
- * Close an open file stream.
- *
- * @param file
- *   The file information.
- *   The file.stream is set to NULL, on both success or on failure.
- *
- * @return
- *   F_none on success.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_access_denied (with error bit) on access denied.
- *   F_block (with error bit) if the action would block and non-blocking is set on the stream.
- *   F_buffer (with error bit) if the buffer is invalid.
- *   F_deadlock (with error bit) if operation would cause a deadlock.
- *   F_file_descriptor (with error bit) if file descriptor is invalid.
- *   F_file_descriptor_max (with error bit) if max file descriptors is reached.
- *   F_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size.
- *   F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
- *   F_input_output (with error bit) on I/O error.
- *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
- *   F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed.
- *   F_space_not (with error bit) if file system is out of space (or file system quota is reached).
- *   F_socket_not (with error bit) if the datagram socket in which a peer has not been set (for socket related streams).
- *
- *   F_file_close (with error bit) on any other error.
- *
- * @see fclose()
- */
-#ifndef _di_f_file_stream_close_
-  extern f_status_t f_file_stream_close(f_file_t * const file);
-#endif // _di_f_file_stream_close_
-
-/**
- * Flush a file stream.
- *
- * @param file
- *   The file information.
- *   The file.id is updated with the file descriptor, if necessary and able.
- *
- * @return
- *   F_none is returned on success.
- *   F_stream_not if file.stream is NULL.
- *   F_file_descriptor_not if file.id is -1.
- *
- *   F_block (with error bit) if file descriptor is set to non-block and the write would result in a blocking operation.
- *   F_buffer (with error bit) if the buffer is invalid.
- *   F_file_closed (with error bit) if file is not open.
- *   F_file_descriptor (with error bit) if the file descriptor is invalid.
- *   F_file_type_directory (with error bit) if file descriptor represents a directory.
- *   F_input_output (with error bit) on I/O error.
- *   F_interrupt (with error bit) if interrupt was received.
- *
- *   F_file_synchronize (with error bit) on any other error.
- *
- * @see fflush()
- */
-#ifndef _di_f_file_stream_flush_
-  extern f_status_t f_file_stream_flush(const f_file_t file);
-#endif // _di_f_file_stream_flush_
-
-/**
- * Open a file stream.
- *
- * The file descriptor is retrieved on success, if necessary and able.
- *
- * If the file stream is open, it is closed before re-opening.
- *
- * This is often used for changing the file pointed to by standard streams such as stdout.
- *
- * @param path
- *   The file path.
- * @param mode
- *   The file modes do use when opening, as an fopen() file mode string.
- *   Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe).
- *   If neither truncate nor append are specified in write only mode, then the failsafe is to append.
- *
- *   File Modes (fopen() file modes vs open file modes):
- *     - "r":  O_RDONLY.
- *     - "w":  O_WRONLY | O_CREAT | O_TRUNC.
- *     - "a":  O_WRONLY | O_CREAT | O_APPEND.
- *     - "r+": O_RDWR.
- *     - "w+": O_RDWR | O_CREAT | O_TRUNC.
- *     - "a+": O_RDWR | O_CREAT | O_APPEND.
- * @param file
- *   The file information.
- *   The file.stream is updated if necessary.
- *   The file.id is updated with the file descriptor, if necessary and able.
- *
- * @return
- *   F_none is returned on success.
- *   F_data_not if both path.used is 0.
- *
- *   F_access_denied (with error bit) on access denied.
- *   F_buffer (with error bit) if the buffer is invalid.
- *   F_busy (with error bit) if file system is too busy to perform write.
- *   F_file_descriptor (with error bit) if unable to load the file descriptor.
- *   F_file_found_not (with error bit) if the file was not found.
- *   F_file_open_max (with error bit) when system-wide max open files is reached.
- *   F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
- *   F_filesystem_quota_block (with error bit) if file system's disk blocks or inodes are exhausted.
- *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
- *   F_loop (with error bit) on loop error.
- *   F_memory_not (with error bit) if out of memory.
- *   F_name (with error bit) on path name is too long.
- *   F_number_overflow (with error bit) on overflow error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_prohibited (with error bit) if file system does not allow for making changes.
- *   F_read_only (with error bit) if file is read-only.
- *   F_supported_not (with error bit) fo unsupported file types.
- *   F_failure (with error bit) for any other error.
- *
- * @see fopen()
- */
-#ifndef _di_f_file_stream_open_
-  extern f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file);
-#endif // _di_f_file_stream_open_
-
-/**
- * Open a file stream from a file descriptor.
- *
- * @param mode
- *   The file modes do use when opening.
- *   Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe).
- *   If neither truncate nor append are not specified in write only mode, then the failsafe is to append.
- *   This should match the modes used to open the file descriptor as it relates to the stream modes.
- * @param file
- *   The file with a valid file descriptor (file.id).
- *
- * @return
- *   F_none is returned on success.
- *   F_file_descriptor_not if file.id is -1.
- *
- *   F_access_denied (with error bit) on access denied.
- *   F_block (with error bit) if the action would block and non-blocking is set on the stream.
- *   F_buffer (with error bit) if the buffer is invalid.
- *   F_deadlock (with error bit) if operation would cause a deadlock.
- *   F_file_descriptor (with error bit) if file descriptor is invalid.
- *   F_file_descriptor_max (with error bit) if max file descriptors is reached.
- *   F_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size.
- *   F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
- *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
- *   F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed.
- *   F_prohibited (with error bit) if file system does not allow for making changes.
- *   F_socket_not (with error bit) if socket is not connected.
- *   F_space_not (with error bit) if the file system is out of space (or file system quota is reached).
- *
- * @see fdopen()
- */
-#ifndef _di_f_file_stream_open_descriptor_
-  extern f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file);
-#endif // _di_f_file_stream_open_descriptor_
-
-/**
- * Read until EOF is reached.
- *
- * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution.
- *
- * @param file
- *   The file to read.
- *   The file.size_read represents the amount to process at a given time.
- * @param buffer
- *   The buffer the file is being read into.
- *   The contents of the file is appended into this buffer.
- *
- * @return
- *   F_none_eof on success and EOF was reached.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_block (with error bit) if file descriptor is set to non-block and the read would result in a blocking operation.
- *   F_buffer (with error bit) if the buffer is invalid.
- *   F_error (with error bit) if the file is already in the error state at the start of this function.
- *   F_file_closed (with error bit) if file is not open.
- *   F_file_descriptor (with error bit) if the file descriptor is invalid.
- *   F_file_type_directory (with error bit) if file descriptor represents a directory.
- *   F_input_output (with error bit) on I/O error.
- *   F_interrupt (with error bit) if interrupt was received.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- * @see flockfile()
- * @see feof_unlocked()
- * @see ferror_unlocked()
- * @see fread_unlocked()
- * @see funlockfile()
- */
-#ifndef _di_f_file_stream_read_
-  extern f_status_t f_file_stream_read(const f_file_t file, f_string_dynamic_t * const buffer);
-#endif // _di_f_file_stream_read_
-
-/**
- * Read until a single block is filled or EOF is reached.
- *
- * To determine how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution.
- *
- * @param file
- *   The file to read.
- *   The file.size_read represents the amount to process at a given time.
- * @param buffer
- *   The buffer the file is being read into.
- *   The contents of the file is appended into this buffer.
- *
- * @return
- *   F_none on success.
- *   F_none_eof on success and EOF was reached.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_error (with error bit) if the file is already in the error state at the start of this function.
- *   F_file_closed (with error bit) if the file is closed.
- *   F_file_read (with error bit) on file read error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- * @see feof_unlocked()
- * @see ferror_unlocked()
- * @see flockfile()
- * @see fread()
- * @see funlockfile()
- */
-#ifndef _di_f_file_stream_read_block_
-  extern f_status_t f_file_stream_read_block(const f_file_t file, f_string_dynamic_t * const buffer);
-#endif // _di_f_file_stream_read_block_
-
-/**
- * Read until a given number or EOF is reached, storing it in the buffer.
- *
- * To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution.
- *
- * This is different from simply using the file.size_read.
- * The file.size_read represents the amount to process at a given time.
- * The total represents the maximum number of file.size_read to process.
- * For example, if file.size_read is 16 and total is 128, then this function would need to be called 8 times until total is reached.
- *
- * @param file
- *   The file to read.
- *   The file.size_read represents the amount to process at a given time.
- * @param total
- *   The total bytes to read, unless EOF is reached first.
- * @param buffer
- *   The buffer the file is being read into.
- *
- * @return
- *   F_none_eof on success and EOF was reached.
- *   F_none_stop on success and total was reached.
- *   F_data_not if total is 0.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_error (with error bit) if the file is already in the error state at the start of this function.
- *   F_file_closed (with error bit) if the file is closed.
- *   F_file_read (with error bit) on file read error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- *   Errors (with error bit) from: f_string_dynamic_increase_by().
- *
- * @see feof_unlocked()
- * @see ferror_unlocked()
- * @see flockfile()
- * @see fread_unlocked()
- * @see funlockfile()
- *
- * @see f_string_dynamic_increase_by()
- */
-#ifndef _di_f_file_stream_read_until_
-  extern f_status_t f_file_stream_read_until(const f_file_t file, const f_array_length_t total, f_string_dynamic_t * const buffer);
-#endif // _di_f_file_stream_read_until_
-
-/**
- * Re-open a file stream.
- *
- * This allows for re-using an existing file stream and possibly file-descriptor.
- *
- * The file descriptor is retrieved on success, if necessary and able.
- *
- * @param path
- *   The file path.
- *   Set path.used to 0 with a non-empty mode (mode.used > 0) to only change the mode of the existing stream.
- * @param mode
- *   The file modes do use when opening.
- *   Set to 0 to determine mode from file.flags (falling back to read only as a failsafe).
- *   If neither truncate nor append are not specified in write only mode, then the failsafe is to append.
- * @param file
- *   The file information.
- *   The file.stream is updated, if necessary.
- *
- * @return
- *   F_none is returned on success.
- *   F_data_not if both path.used and mode.used are 0.
- *
- *   F_access_denied (with error bit) on access denied.
- *   F_buffer (with error bit) if the buffer is invalid.
- *   F_busy (with error bit) if file system is too busy to perform write.
- *   F_file_descriptor (with error bit) if unable to load the file descriptor.
- *   F_file_found_not (with error bit) if the file was not found.
- *   F_file_open_max (with error bit) when system-wide max open files is reached.
- *   F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
- *   F_filesystem_quota_block (with error bit) if file system's disk blocks or inodes are exhausted.
- *   F_interrupt (with error bit) when program received an interrupt signal, halting operation.
- *   F_loop (with error bit) on loop error.
- *   F_memory_not (with error bit) if out of memory.
- *   F_name (with error bit) on path name is too long.
- *   F_number_overflow (with error bit) on overflow error.
- *   F_parameter (with error bit) if a parameter is invalid.
- *   F_prohibited (with error bit) if file system does not allow for making changes.
- *   F_read_only (with error bit) if file is read-only.
- *   F_supported_not (with error bit) fo unsupported file types.
- *   F_failure (with error bit) for any other error.
- *
- * @see fileno()
- * @see freopen()
- */
-#ifndef _di_f_file_stream_reopen_
-  extern f_status_t f_file_stream_reopen(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file);
-#endif // _di_f_file_stream_reopen_
-
-/**
- * Write until entire buffer is written.
- *
- * @param file
- *   The file to write to.
- *   The file must already be open.
- *   The file.size_write represents the amount to process at a given time.
- * @param buffer
- *   The buffer to write to the file.
- * @param written
- *   (optional) The total bytes written.
- *   Set to NULL to not use.
- *
- * @return
- *   F_none on success.
- *   F_none_eof when the file stream is at the end of the file.
- *   F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file).
- *   F_data_not on success but buffer.used is 0.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_file_write (with error bit) on error during file write.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- *   F_file_write (with error bit) on any other error.
- *
- * @see ferror_unlocked()
- * @see flockfile()
- * @see fwrite_unlocked()
- * @see funlockfile()
- */
-#ifndef _di_f_file_stream_write_
-  extern f_status_t f_file_stream_write(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written);
-#endif // _di_f_file_stream_write_
-
-/**
- * Write until a single block is filled or entire buffer is written.
- *
- * To check how much was write into the buffer, record buffer->used before execution and compare to buffer->used after execution.
- *
- * @param file
- *   The file to write to.
- *   The file must already be open.
- *   The file.size_write represents the amount to process at a given time.
- * @param buffer
- *   The buffer to write to the file.
- * @param written
- *   (optional) The total bytes written.
- *   Set to NULL to not use.
- *
- * @return
- *   F_none on success.
- *   F_none_eof when the file stream is at the end of the file.
- *   F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file).
- *   F_data_not on success but buffer.used is 0.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_file_write (with error bit) on error during file write.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- *   F_file_write (with error bit) on any other error.
- *
- * @see flockfile()
- * @see fwrite_unlocked()
- * @see ferror_unlocked()
- * @see funlockfile()
- */
-#ifndef _di_f_file_stream_write_block_
-  extern f_status_t f_file_stream_write_block(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written);
-#endif // _di_f_file_stream_write_block_
-
-/**
- * Write until a given number or entire buffer is written.
- *
- * @param file
- *   The file to write to.
- *   The file must already be open.
- *   The file.size_write represents the amount to process at a given time.
- * @param buffer
- *   The buffer to write to the file.
- * @param total
- *   The total bytes to write, unless end of buffer is reached first.
- * @param written
- *   (optional) The total bytes written.
- *   Set to NULL to not use..
- *
- * @return
- *   F_none on success.
- *   F_none_eof when the file stream is at the end of the file.
- *   F_none_eos on success but range.stop exceeded buffer.used (only wrote up to buffer.used).
- *   F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file).
- *   F_data_not on success but either buffer.used or total is 0.
- *   F_stream_not if file.stream is NULL.
- *
- *   F_file_write (with error bit) on error during file write.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- *   F_file_write (with error bit) on any other error.
- *
- * @see flockfile()
- * @see fwrite_unlocked()
- * @see ferror_unlocked()
- * @see funlockfile()
- */
-#ifndef _di_f_file_stream_write_until_
-  extern f_status_t f_file_stream_write_until(const f_file_t file, const f_string_static_t buffer, const f_array_length_t total, f_array_length_t * const written);
-#endif // _di_f_file_stream_write_until_
-
-/**
- * Write a given range within the buffer.
- *
- * @param file
- *   The file to write to.
- *   The file.size_write represents the amount to process at a given time.
- * @param buffer
- *   The buffer to write to the file.
- * @param range
- *   An inclusive start an stop range within the buffer to read.
- * @param written
- *   (optional) The total bytes written.
- *   Set to NULL to not use.
- *
- * @return
- *   F_none on success.
- *   F_none_stop on success but no data was written (written == 0) (not an error and often happens if file type is not a regular file).
- *   F_none_eos on success but range.stop exceeded buffer.used (only wrote up to buffer.used).
- *   F_stream_not if file.stream is NULL.
- *
- *   F_file_write (with error bit) on error during file write.
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- * @see fwrite_unlocked()
- */
-#ifndef _di_f_file_stream_write_range_
-  extern f_status_t f_file_stream_write_range(const f_file_t file, const f_string_static_t buffer, const f_string_range_t range, f_array_length_t * const written);
-#endif // _di_f_file_stream_write_range_
-
-
-/**
  * Update the files access and modification timestamp, creating the file if it does not already exist.
  *
  * When the file is created, it is created as a regular file.
index b7f197f4caa4d69ffa80c2a85c893450f3837ba2..b1883fec1615c6583ab8728c6a177af3fed493ef 100644 (file)
@@ -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 (file)
index 0000000..5938412
--- /dev/null
@@ -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 (file)
index 0000000..a5b3fc0
--- /dev/null
@@ -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
index 5e7561e540a1b2a220b1586edbf6c2d934869a0a..0ed2726f3df1e4d4212933af85c1e8d2b22b2990 100644 (file)
@@ -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
index d467aacf9b923a5fdf9ee90d1ee50b11ff87e84a..33eb42981b1974c5fb420a8677656c397920d442 100644 (file)
@@ -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
index d6d3b59894b5877274bc6ffad2a5f37a35786f2b..9e9cc5b056971af11730d6c4e3ef6e978360b936 100644 (file)
@@ -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.
index 2b897fad3742632593a25d682333a1ef8e730bb5..0e5cb973afc00f63f6edc68af52232ed1fdaba79 100644 (file)
@@ -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,
index 20d64578af45edf2db86742fb54cd1c1f32d33ef..11b626009c402334a2f6919d99ff2c5e0b03663b 100644 (file)
@@ -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;
 
index b8199dd39be2b40b166201acedd2d1743075fb27..56bea80a0d3f98f2b23c0b145b8c302b219edb7e 100644 (file)
@@ -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;
index 80f7e62fc658de594bb0556b1d7a6a4adac0e819..9e1064d61ec6c211a354b066d57df4c4cae0670a 100644 (file)
@@ -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;
 
index 2971f6974a34ebbbc19ed0458b026ed1cf78c763..72c2fe931911ecb8fced889c769eb76baabb1af7 100644 (file)
@@ -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;
   }
index 79c86da45b83c91b6456da6e34a375303edd8f01..b433bfb3987cf0558bca1a718ad7327183ae10f5 100644 (file)
@@ -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_)
 
 /**
index 7ba650fc278829a190c39ed33ca6ce69475ebc2b..d3afb00ee52900be1640498dc21de3b4c79c109e 100644 (file)
@@ -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;
   }
index 22a71cee158af2c7c097dafeef3e16d240e58458..ccda4f8e8225d0f7745b74b904d439ce8a650488 100644 (file)
 
 // FLL-2 program includes.
 #include <fll/level_2/program/common.h>
+#include <fll/level_2/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 output
- *   The file stream to output to.
- * @param context
- *   The color context.
- * @param name
- *   The name of the program.
- * @param version
- *   The version number of the program.
- *
- * @return
- *   F_none on success.
- *
- * @see f_print_terminated()
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_help_header_
-  extern f_status_t fll_program_print_help_header(const f_file_t output, const f_color_context_t context, const f_string_static_t name, const f_string_static_t version);
-#endif // _di_fll_program_print_help_header_
-
-/**
- * Print standard help option.
- *
- * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called.
- *
- * @param output
- *   The file stream to output to.
- * @param context
- *   The color context.
- * @param option_short
- *   The short name of the option.
- * @param option_long
- *   The long name of the option.
- * @param symbol_short
- *   The short symbol of the option.
- * @param symbol_long
- *   The long symbol of the option.
- * @param description
- *   A desciption associated with the option.
- *
- * @return
- *   F_none on success.
- *
- * @see f_print_terminated()
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_help_option_
-  extern f_status_t fll_program_print_help_option(const f_file_t output, const f_color_context_t context, const f_string_static_t option_short, const f_string_static_t option_long, const f_string_static_t symbol_short, const f_string_static_t symbol_long, const char *description);
-#endif // _di_fll_program_print_help_option_
-
-/**
- * Print standard help option (long option only).
- *
- * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called.
- *
- * @param output
- *   The file stream to output to.
- * @param context
- *   The color context.
- * @param option_long
- *   The long name of the option.
- * @param symbol_long
- *   The long symbol of the option.
- * @param description
- *   A desciption associated with the option.
- *
- * @return
- *   F_none on success.
- *
- * @see f_print_terminated()
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_help_option_long_
-  extern f_status_t fll_program_print_help_option_long(const f_file_t output, const f_color_context_t context, const f_string_static_t option_long, const f_string_static_t symbol_long, const char *description);
-#endif // _di_fll_program_print_help_option_long_
-
-/**
- * Print standard help option (other option only).
- *
- * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called.
- *
- * @param output
- *   The file stream to output to.
- * @param context
- *   The color context.
- * @param option_other
- *   The other name of the option.
- * @param description
- *   A desciption associated with the option.
- *
- * @return
- *   F_none on success.
- *
- * @see f_print_terminated()
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_help_option_other_
-  extern f_status_t fll_program_print_help_option_other(const f_file_t output, const f_color_context_t context, const f_string_static_t option_other, const char *description);
-#endif // _di_fll_program_print_help_option_other_
-
-/**
- * Print all standard help options.
- *
- * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called.
- *
- * @param output
- *   The file stream to output to.
- * @param context
- *   The color context.
- *
- * @return
- *   F_none on success.
- *
- * @see f_print_terminated()
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_help_option_standard_
-  extern f_status_t fll_program_print_help_option_standard(const f_file_t output, const f_color_context_t context);
-#endif // _di_fll_program_print_help_option_standard_
-
-/**
- * Print standard help usage.
- *
- * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called.
- *
- * @param output
- *   The file stream to output to.
- * @param context
- *   The color context.
- * @param name
- *   The name of the program.
- * @param parameters
- *   (optional) The non-option parameters to be displayed inside the brackets.
- *   Set the first array value to EOS to disable printing of parameters.
- *   Set parameters.used to 0 to disable.
- *
- * @return
- *   F_none on success.
- *
- * @see f_print_terminated()
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_help_usage_
-  extern f_status_t fll_program_print_help_usage(const f_file_t output, const f_color_context_t context, const f_string_static_t name, const f_string_static_t parameters);
-#endif // _di_fll_program_print_help_usage_
-
-/**
- * Print the program version.
- *
- * This print function does not use locking, be sure something like flockfile() and funlockfile() are appropriately called.
- *
- * @param output
- *   The file stream to output to.
- * @param version
- *   The version number of the program.
- *
- * @return
- *   F_none on success.
- *
- * @see fl_print_format()
- */
-#ifndef _di_fll_program_print_version_
-  extern f_status_t fll_program_print_version(const f_file_t output, const f_string_static_t version);
-#endif // _di_fll_program_print_version_
-
-/**
  * Determine the color context from the parameters and then set the color context based on the choice.
  *
  * This will allow for the color context and the color sets to be safely used when colors are disabled.
@@ -501,6 +333,7 @@ extern "C" {
  *
  * @param main
  *   The main program data.
+ *   The main->signal must be used to designate blocked signals.
  *
  * @return
  *   A positive number representing a valid signal on signal received.
diff --git a/level_2/fll_program/c/program/print.c b/level_2/fll_program/c/program/print.c
new file mode 100644 (file)
index 0000000..285cebb
--- /dev/null
@@ -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 (file)
index 0000000..7568fb9
--- /dev/null
@@ -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
index 76dcafb2580b056828f43613fdd411f2ff5dcf0c..081fa82ae994e4b5d04312b8a4924c54a4ab377e 100644 (file)
@@ -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
index 529a76a800d5dd4d5d8167a2d1bb8de58b763dbe..d23bbd3a4a6fc6c6d951363bab532f4d48e98ced 100644 (file)
@@ -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;
 
index bbeb216b0400f2cd88bfae1563755fa86e6db7d7..f23e81163861517d6cc0c9ccd2b026a54894beff 100644 (file)
@@ -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;
     }
index f25b91a734e410ea48a6f3118635b149878a35de..893b430a1b66a0e268f9194882aa8646afef3a08 100644 (file)
@@ -54,23 +54,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- *
- * @see byte_dump_main()
- */
-#ifndef _di_byte_dump_print_help_
-  extern f_status_t byte_dump_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_byte_dump_print_help_
-
-/**
  * Execute main program.
  *
  * @param main
@@ -95,9 +78,75 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_byte_dump_main_
-  extern f_status_t byte_dump_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t byte_dump_main(fll_program_data_t * const main, byte_dump_setting_t * const setting);
 #endif // _di_byte_dump_main_
 
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *   This does not alter setting.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_byte_dump_setting_delete_
+  extern f_status_t byte_dump_setting_delete(byte_dump_setting_t * const setting);
+#endif // _di_byte_dump_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately retuns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *
+ *   This alters setting.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_byte_dump_setting_load_
+  extern void byte_dump_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, byte_dump_setting_t * const setting);
+#endif // _di_byte_dump_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *   This does not alter setting.status.
+ *   All buffers are deallocated.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_byte_dump_setting_unload_
+  extern f_status_t byte_dump_setting_unload(fll_program_data_t * const main, byte_dump_setting_t * const setting);
+#endif // _di_byte_dump_setting_unload_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index a9659c7ddd4296ce6279cfe4701fabbe2cbdcc19..53e56aa2ea5ad4f8bf54c373770615d2ebd45046 100644 (file)
@@ -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
index 17e88a91c23963c6d689fea0e891b9204d9a5413..df5c7ec53bd468373b436525e6bac5214ce9e043 100644 (file)
@@ -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
index f05e1b093ad9fc9767313b90f45df6fad2ed8839..d32ca7f7f9787eb14c47dba4500c586c330a79d9 100644 (file)
@@ -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 (file)
index 0000000..da007da
--- /dev/null
@@ -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 (file)
index 0000000..311a6a3
--- /dev/null
@@ -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
index 2d94f9691dffe7a4ce4253b7dc1f29a4e219d471..d72dac89501db257e2ec70b9a2702f1ac871146d 100644 (file)
@@ -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);
           }
index 54d8b21668db178faa4de01a699e12e63672d91d..820be9031957c1b49c779545c20abb52682caebe 100644 (file)
@@ -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
index de72becb9871fe2b99c1916914fe57260afedd2c..12c01cbe963676998032c952dffcea08475e8772 100644 (file)
@@ -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
index 348b33894764d54340cd23f3744eb576122b83c1..ce543f92ddfc0430b749810c761a9c6fe9ed9284 100644 (file)
@@ -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
index 846c3d57d4a90d34c9a81b391041ca3e2387f719..550fde8b9fa41022716ed56f84e6fd78479644ee 100644 (file)
@@ -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
index 1e77a7d65ea3541375b7b9b4cc1a8fc0bcfa0d2a..3712dfe74143c3b030aad143543fc76ea15906a9 100644 (file)
@@ -188,6 +188,66 @@ extern "C" {
 #endif // _di_control_payload_types_
 
 /**
+ * Flags used to represent flags passed to the main function.
+ *
+ * control_main_flag_*_e:
+ *   - none:          No modes in use.
+ *   - file_from:     Using a specified source file.
+ *   - file_to:       Using a specified destination file.
+ *   - help:          Print help.
+ *   - header:        Enable printing of headers.
+ *   - separate:      Enable printing of separators.
+ *   - strip_invalid: Using strip invalid character mode.
+ *   - verify:        Using verify mode.
+ *   - version:       Print version.
+ */
+#ifndef _di_control_main_flag_e_
+  enum {
+    control_main_flag_none_e          = 0x0,
+    control_main_flag_file_from_e     = 0x1,
+    control_main_flag_file_to_e       = 0x2,
+    control_main_flag_header_e        = 0x4,
+    control_main_flag_help_e          = 0x8,
+    control_main_flag_separate_e      = 0x10,
+    control_main_flag_strip_invalid_e = 0x20,
+    control_main_flag_verify_e        = 0x40,
+    control_main_flag_version_e       = 0x80,
+  };
+#endif // _di_control_main_flag_e_
+
+/**
+ * The control main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * flag: Flags passed to the main function.
+ *
+ * status: The main status code, generally used by the load settings and main functions.
+ *
+ * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not.
+ * line_last:  A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not.
+ */
+#ifndef _di_control_setting_t_
+  typedef struct {
+    uint16_t flag;
+
+    f_status_t status;
+
+    f_string_static_t line_first;
+    f_string_static_t line_last;
+  } control_setting_t;
+
+  #define control_setting_t_initialize \
+    { \
+      control_main_flag_none_e, \
+      F_none, \
+      f_string_static_t_initialize, \
+      f_string_static_t_initialize, \
+    }
+#endif // _di_control_setting_t_
+
+/**
  * Identify the action code the given name represents.
  *
  * @param action
@@ -243,6 +303,72 @@ extern "C" {
   extern f_string_static_t control_payload_type_name(const uint8_t type);
 #endif // _di_control_payload_type_name_
 
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *   This does not alter setting.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_control_setting_delete_
+  extern f_status_t control_setting_delete(control_setting_t * const setting);
+#endif // _di_control_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately retuns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *
+ *   This alters setting.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_control_setting_load_
+  extern void control_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, control_setting_t * const setting);
+#endif // _di_control_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *   This does not alter setting.status.
+ *   All buffers are deallocated.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_control_setting_unload_
+  extern f_status_t control_setting_unload(fll_program_data_t * const main, control_setting_t * const setting);
+#endif // _di_control_setting_unload_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 91c9c21025f9e8828c4f3d1b8b6cdabb1903ace1..4c2864b2aaba1f3a0a8d0faf10f04d21d3871e35 100644 (file)
@@ -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;
     }
index a1f387d892ee6e1cd98fe1845f5287dcbcb2dd7e..980be6c9ca665acff200e6d12fe403dbffdc46cd 100644 (file)
@@ -58,21 +58,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param main
- *   The main program data.
- *
- * @return
- *   F_none on success.
- *
- * @see control_main()
- */
-#ifndef _di_control_print_help_
-  extern f_status_t control_print_help(const fll_program_data_t * const main);
-#endif // _di_control_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -96,7 +81,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_control_main_
-  extern f_status_t control_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t control_main(fll_program_data_t * const main, control_setting_t * const setting);
 #endif // _di_control_main_
 
 #ifdef __cplusplus
index 4c909ac2fd3c5ca4e728a7165586e5130bd66e20..910a490b61b86143638acab8c571bc2f30a4a654 100644 (file)
@@ -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 (file)
index 0000000..66872e5
--- /dev/null
@@ -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 (file)
index 0000000..d0fbdea
--- /dev/null
@@ -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
index 4963f400c57c1e9a200110f8b4a86962211e0da9..8fdfaefa6a651a536cd2311d435916cdcc133a73 100644 (file)
@@ -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) {
 
index 3241e2e465650267fc66dae3e956530a1adb3e12..d136ec124b3cd47a0bca39231a1f865f4bc9f3a8 100644 (file)
@@ -309,18 +309,6 @@ extern "C" {
 #endif // _di_control_print_error_socket_file_not_
 
 /**
- * Print a message about a process signal being recieved, such as an interrupt signal.
- *
- * @param main
- *   The main program data.
- * @param signal
- *   The signal received.
- */
-#ifndef _di_control_print_signal_received_
-  extern void control_print_signal_received(const fll_program_data_t * const main, const f_status_t signal) F_attribute_visibility_internal_d;
-#endif // _di_control_print_signal_received_
-
-/**
  * Print a warning message about a response header being repeated (when debugging).
  *
  * This program currently does not support multiple headers for any given valid header Object.
index 39ea2d1bdd8cb212561c9018575542ae9c372146..f5f42a5fc4e79128d340440b5f342492c4e08d55 100644 (file)
@@ -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
index 3d4d1021607c961747827bf60cfdaddc42892070..c73b693100b6d7b1c8becacfeab9cb3678691aff 100644 (file)
@@ -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
index be9d88c44cc6f7606265a40ce8a9d076aaac65c8..bd62ff94f7a0cc3cb9ab4e3d5ac54c9eb9d95a29 100644 (file)
@@ -446,6 +446,66 @@ extern "C" {
 #endif // _di_controller_resource_limit_t_
 
 /**
+ * Flags used to represent flags passed to the main function.
+ *
+ * controller_main_flag_*_e:
+ *   - none:          No modes in use.
+ *   - file_from:     Using a specified source file.
+ *   - file_to:       Using a specified destination file.
+ *   - help:          Print help.
+ *   - header:        Enable printing of headers.
+ *   - separate:      Enable printing of separators.
+ *   - strip_invalid: Using strip invalid character mode.
+ *   - verify:        Using verify mode.
+ *   - version:       Print version.
+ */
+#ifndef _di_controller_main_flag_e_
+  enum {
+    controller_main_flag_none_e          = 0x0,
+    controller_main_flag_file_from_e     = 0x1,
+    controller_main_flag_file_to_e       = 0x2,
+    controller_main_flag_header_e        = 0x4,
+    controller_main_flag_help_e          = 0x8,
+    controller_main_flag_separate_e      = 0x10,
+    controller_main_flag_strip_invalid_e = 0x20,
+    controller_main_flag_verify_e        = 0x40,
+    controller_main_flag_version_e       = 0x80,
+  };
+#endif // _di_controller_main_flag_e_
+
+/**
+ * The controller main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * flag: Flags passed to the main function.
+ *
+ * status: The main status code, generally used by the load settings and main functions.
+ *
+ * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not.
+ * line_last:  A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not.
+ */
+#ifndef _di_controller_setting_t_
+  typedef struct {
+    uint16_t flag;
+
+    f_status_t status;
+
+    f_string_static_t line_first;
+    f_string_static_t line_last;
+  } controller_setting_t;
+
+  #define controller_setting_t_initialize \
+    { \
+      controller_main_flag_none_e, \
+      F_none, \
+      f_string_static_t_initialize, \
+      f_string_static_t_initialize, \
+    }
+#endif // _di_controller_setting_t_
+
+/**
  * Identify the payload code the given name represents.
  *
  * @param payload
@@ -636,6 +696,72 @@ extern "C" {
   extern f_string_static_t controller_rule_setting_limit_type_name(const uint8_t type);
 #endif // di_controller_rule_setting_limit_type_name_
 
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *   This does not alter setting.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_controller_setting_delete_
+  extern f_status_t controller_setting_delete(controller_setting_t * const setting);
+#endif // _di_controller_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately retuns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *
+ *   This alters setting.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_controller_setting_load_
+  extern void controller_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, controller_setting_t * const setting);
+#endif // _di_controller_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *   This does not alter setting.status.
+ *   All buffers are deallocated.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_controller_setting_unload_
+  extern f_status_t controller_setting_unload(fll_program_data_t * const main, controller_setting_t * const setting);
+#endif // _di_controller_setting_unload_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 8c3daf3fdec59186dba705034f078d9d420e41f5..595d63f42e03fec80e8925d5a0d72f2fca552edd 100644 (file)
 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);
 
index 3e3e0322a38f71f8275290064a8c2c03e8f5e51b..d3ae9b568434d3af3cb46d604910c96c48ac1885 100644 (file)
@@ -82,21 +82,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param main
- *   The main program data.
- *
- * @return
- *   F_none on success.
- *
- * @see controller_main()
- */
-#ifndef _di_controller_print_help_
-  extern f_status_t controller_print_help(controller_main_t * const main);
-#endif // _di_controller_print_help_
-
-/**
  * Execute main program.
  *
  * Be sure to call controller_main_delete() after executing this.
index 230c99ed81cda095fa454d1853ca82b350717757..863c3a3110591414642a159c280d32896a9f8351 100644 (file)
@@ -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
index 451ac21e4c81e852ec8a6a95c5d9dc9563e4fdb1..ffce643c81b7c27c8b7a5d528de863a890a843b7 100644 (file)
@@ -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
index 5613eece6906060af133a67d359a6096de54fb55..0d53d9e8186acc5e4dab53229ac3da4accc8d110 100644 (file)
@@ -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);
index 39d9cda8d89f54b7ac0c615dee514ed989d2c300..9a81235143bbd8383aecd5b5f4ed0daa8a95d1f5 100644 (file)
@@ -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 (file)
index 0000000..4e41cd3
--- /dev/null
@@ -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 (file)
index 0000000..c791d96
--- /dev/null
@@ -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
index d5b401a37c34319b49a57cd6773b071c8f8f98a2..b44898812eb4f1e284300de0117e5a5ec3e4103d 100644 (file)
@@ -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);
index 299a0b2f6107a070d54aa66eff94ec0af02e7727..4e0a994d7e6a8f880a96df0828d697a39b2355f7 100644 (file)
@@ -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
 
index 7565db19616381e22027572284f4038bb24a9e8a..9f06812f4be988ba1ea81d679bf2f562bc3962a5 100644 (file)
@@ -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
index 3dc0044c256fe177ae54e2a9221f8152a3981ab2..46ec2b04a6f5a26e613569ff36f1a66975bffd29 100644 (file)
@@ -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
index 273d14652a6bbe2dbc5fa7c00365580cd6d73a0b..002dcf6c9d0d2a9781eacee57786322cf198b0e7 100644 (file)
 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);
 
index 7c7a32640cfdf4a752893505fd2c1279b0272044..972d3268ad07a9ae07430f953d1ea7c4b347f7b1 100644 (file)
@@ -97,21 +97,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fake_print_help_
-  extern f_status_t fake_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fake_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -136,7 +121,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fake_main_
-  extern f_status_t fake_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fake_main(fll_program_data_t * const main, fake_setting_t * const setting);
 #endif // _di_fake_main_
 
 /**
index 75db8a37c94bdc992bb02a82b6a228c6c9f265c1..1a1da04d4927e9c7ece9843f448b62775d2fa9fa 100644 (file)
  */
 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 (file)
index 0000000..ab66530
--- /dev/null
@@ -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 (file)
index 0000000..4f10ebd
--- /dev/null
@@ -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
index 51c0707f06cc91ac4930cd19742b46113b50884a..3faf7487c4c87321947df11ce15624c6600ea18d 100644 (file)
@@ -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);
 
index df4bc55b1ce4a301e1d9a8b675d53f4a598cb4d9..99f1d16f6e38a713fb002ab784bd044a1143a1ea 100644 (file)
@@ -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);
 
index a847f01bdcc6b1846726fb95e9f89baf292344d7..fd5bd8f50d3338f341dbfc7c54cb2e4bc4f15b36 100644 (file)
@@ -46,7 +46,7 @@ extern "C" {
       *status = fll_execute_program(program, arguments, &parameter, 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);
     }
index 26e3372e455deb2229ae92a7c9fff108592d6631..d63b29ce581b11e9ff165040c264f31c634195ed 100644 (file)
@@ -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);
 
index d869d4df9f189117a0f2516871bf7c99d5312ccb..501f3da3343f39e7dcf838a8628a53cbf1e3c1ff 100644 (file)
@@ -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);
 
index 941910c76976e3b19f79a9ea563961b1312fc1a6..80f271490f8441d7f635183bc4e5543657df51aa 100644 (file)
@@ -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, &parameter, 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);
     }
index d2d06f309dd473fd4842c7f492ed6cec7bb05fa3..6213226630a63d64f14a6e6ff3a9b6ac26898f0b 100644 (file)
@@ -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) {
 
index 43381f7fa2ea5135bc335992d2b9fa9b477857f7..02ba75e758bcfc8f2dc268549c71ee08c16b75c0 100644 (file)
@@ -352,21 +352,6 @@ extern "C" {
 #endif // _di_fake_print_message_section_operation_unknown_
 
 /**
- * Print a message about a process signal being recieved, such as an interrupt signal.
- *
- * @param data
- *   The program data.
- *
- * @see flockfile()
- * @see funlockfile()
- *
- * @see fl_print_format()
- */
-#ifndef _di_fake_print_signal_received_
-  extern void fake_print_signal_received(fake_data_t * const data) F_attribute_visibility_internal_d;
-#endif // _di_fake_print_signal_received_
-
-/**
  * Print message when fake settings content is empty.
  *
  * @param data
index f776a894b849b0988dbca492e22cd061ec0b8d76..9c80dfc600896200b9ab96b0fd1bb0df523f1f4c 100644 (file)
@@ -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
index 2a64521bc8514ed178b718edc416f5dbf934be9d..e921ce912da74422cba378e55bb4b2b8e4e1a502 100644 (file)
@@ -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
index 410a4bc306fdc1406b5d3d98121cb71cf82c171b..b6893ed040ad85fc1399204fff31dbf0f3f6df3d 100644 (file)
@@ -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
index 7bb364e372eac0c70bbc8797f95d695b7dd73f23..ca0f6303d1fa32d8d570d3ac87d6cfe0427ab952 100644 (file)
 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;
     }
index 37032a5f9a90772bd0e4e6c88de4f258dcef2f51..b05ec3ca28213fad19c98dd778cb9bf3d1138060 100644 (file)
@@ -55,21 +55,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_firewall_print_help_
-  extern f_status_t firewall_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_firewall_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -93,7 +78,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_firewall_main_
-  extern f_status_t firewall_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t firewall_main(fll_program_data_t * const main, firewall_setting_t * const setting);
 #endif // _di_firewall_main_
 
 #ifdef __cplusplus
index 6a931ef8d21043c569747002606f39b14d690254..09a0c725bfe0472bdc86c2e246c429f13bc33625 100644 (file)
@@ -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 (file)
index 0000000..7c2eaea
--- /dev/null
@@ -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 (file)
index 0000000..f7ff2c4
--- /dev/null
@@ -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
index dadb9e240da4ab410644e2f81186d88d1f84731f..d20e7567fa3728e59afd60b64ad5f93c2c7e5356 100644 (file)
@@ -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) {
 
index 461cb908d437aa305ebb1892e7e9368144823131..b2c3b41b5825bf86a821c7999076c2b981529208 100644 (file)
@@ -189,18 +189,6 @@ extern void firewall_print_error_on_unhandled(const fl_print_t output, const cha
 extern void firewall_print_error_on_unhandled_for_file(const fl_print_t output, const char *function, const f_status_t status, const f_string_static_t filename) F_attribute_visibility_internal_d;
 
 /**
- * Print a message about a process signal being recieved, such as an interrupt signal.
- *
- * @param data
- *   The program data.
- * @param signal
- *   The signal received.
- */
-#ifndef _di_firewall_print_signal_received_
-  extern void firewall_print_signal_received(firewall_data_t * const data, const f_status_t signal) F_attribute_visibility_internal_d;
-#endif // _di_firewall_print_signal_received_
-
-/**
  * Check to see if a process signal is received.
  *
  * Only signals that are blocked via main.signal will be received.
index 223d8678865545cb49fc230dbb1f5337ac40aeb7..4da5bf3e2e0b7e6698c92d6cf0483cad6fcf82ea 100644 (file)
@@ -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
 
index a31922b93c5c1f7e56647483460e8cf48c9d4265..63fb628dac1a6bf23a3165b82e8ce420656591ef 100644 (file)
@@ -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
index d5b5285e7b73d67649541cbd68456c676391e9be..e2aca27137e7bbe72b3bfbe98152fed4d6406388 100644 (file)
@@ -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
index 53f2c8eebad027b09d1b56765af525f6979db376..1abbed33793da8e6793e22d36a4a6baa8dfc6b7f 100644 (file)
@@ -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);
 
index 857aca433a103c0821908bc03a732639a1871863..d6bc982b7a6152831a1742e7ffe9da946462da3d 100644 (file)
@@ -55,21 +55,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_basic_list_read_print_help_
-  extern f_status_t fss_basic_list_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_basic_list_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -91,7 +76,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fss_basic_list_read_main_
-  extern f_status_t fss_basic_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_basic_list_read_main(fll_program_data_t * const main, fss_basic_list_read_setting_t * const setting);
 #endif // _di_fss_basic_list_read_main_
 
 #ifdef __cplusplus
index eac0224161840569fac561b6566daacf4e5673af..f4f6dbcf582af6570efda7904d4f073b55fbb41d 100644 (file)
@@ -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 (file)
index 0000000..c74adf8
--- /dev/null
@@ -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 (file)
index 0000000..d75c2f3
--- /dev/null
@@ -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
index 7f1e7e850c0496030ebf730ac39d64372e992823..a1861b3b5cafa399dfea50b7fc2da31095547b71 100644 (file)
@@ -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
index 75cd604c0c6bc708306ea0a19a0d02e63ace943f..7e94adbb2a0212ba06501c1bff79bb57862f001f 100644 (file)
@@ -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
index d327877c442ade249e55b6e5b589460b038bfc2d..74c033351a406dc57cd7e022cc20a9be658ed438 100644 (file)
@@ -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);
         }
index 1bd1919749ef7e36b16cbea7d10d68e45385e533..66d740ece433dcee94e45b1e160a51a60cf4a5f8 100644 (file)
@@ -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
index 87f363eaee132e236f52d258d611d63e0357347b..b3b13296b41c7f6537d695e248011dbf0d60b6fb 100644 (file)
@@ -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
index 3a7985b269e5f288b727c7ea28178bf03a717fc5..6712563782f6b0ca7ea4d0a09fa0bebeb3614107 100644 (file)
@@ -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
index 3c233d0a64bb0c1fb1a9c786e47c68d0041dc635..311fb52c7375866351eafba8130841fd57dbac02 100644 (file)
@@ -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);
 
index 7e896fcc3700c891c4e476c80da84e9342f34c06..251c71942cb1e58622552e7ef9973f7e36e2fd0f 100644 (file)
@@ -47,21 +47,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_basic_list_write_print_help_
-  extern f_status_t fss_basic_list_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_basic_list_write_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -74,16 +59,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_basic_list_write_main_
-  extern f_status_t fss_basic_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_basic_list_write_main(fll_program_data_t * const main, fss_basic_list_write_setting_t * const setting);
 #endif // _di_fss_basic_list_write_main_
 
 #ifdef __cplusplus
index 180951474fbd94ca44b7a93d7c26350df2c4c83b..fd6a53bdb69d6c82c65f35cf2ed80c040fcfc8b1 100644 (file)
@@ -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 (file)
index 0000000..10b3659
--- /dev/null
@@ -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 (file)
index 0000000..12ddbc0
--- /dev/null
@@ -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
index d62960d64a080c02c8f2b8b6eff98390445aaadb..19754919242208ed1bfda68152dfa5f8108aee05 100644 (file)
@@ -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
index b4be76a924eb891ea37ee9b330585f5cf709138b..13524a4c743461906bff90bdecfcc694f264ccb2 100644 (file)
@@ -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
index 62ee9dd5798b0067c0392311cc659691b00bdf1a..4d3d125e8601c2bdd00890ecfd6dffefc12f4a14 100644 (file)
@@ -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);
 
index 2168e1469d917ed4445a48fd5d01b44c8e920ff3..f92a44890a3a8e72f51e9c2c0d6d26e8f299f5ed 100644 (file)
@@ -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
index b9c097ab236f0f15250d83305e92c99763d67381..923d37c07e7d68b0d047d882bfda9cbd1902de57 100644 (file)
@@ -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
index 33b2f016997093bfd04fde35924f9666a1c4de49..d02c6fd99b7c871146b35a7df6a84ffca5aacfff 100644 (file)
@@ -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
index 71a178b3062a03b57d844401c4e161831b5bb444..5aee79cf926b57068cd17d9d818c97e4c0948d1f 100644 (file)
@@ -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);
 
index aac0e6b7889b837df8d280672b280db4801eafe5..acc481f0958a60d7b8dc5b86a8f6d8d57e1e770e 100644 (file)
@@ -55,21 +55,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_basic_read_print_help_
-  extern f_status_t fss_basic_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_basic_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -82,16 +67,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_basic_read_main_
-  extern f_status_t fss_basic_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_basic_read_main(fll_program_data_t * const main, fss_basic_read_setting_t * const setting);
 #endif // _di_fss_basic_read_main_
 
 #ifdef __cplusplus
index ddd18479b4f416fbaa709e641978ea14723f7ec5..33b3e5880efa98791ffd17d5423fc9b4b50366e9 100644 (file)
@@ -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 (file)
index 0000000..13fd2b3
--- /dev/null
@@ -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 (file)
index 0000000..ae20be3
--- /dev/null
@@ -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
index d89a23acc8ff554218cb99330287e8972de0dd3e..0bfe454813d76c3acc0c904b8d095c23f20530a7 100644 (file)
@@ -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
index e942aca6591ab817337fe370d7e2eed9285da34c..4f8b126a6586803a0475bbcc936aef5a0b67d3be 100644 (file)
@@ -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
index 28760fc896bf7a208a8ec90f6ee3f8fe4d36644c..657a5d4e0237e78a71bc37caa3014bdf81aa31f6 100644 (file)
@@ -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);
         }
index 081696b9a35063fc5e62b3bd21949bbbecb25764..f78b282073ab47d31a888a8c3332901399039cd9 100644 (file)
@@ -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
index f417c1f47882e0e80b18783460ecce7d6ff5594e..4e4edf15a11f5abefa6968cc323f1cfb2c4d8b42 100644 (file)
@@ -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
index c0764f4d0bfc8a982aabcc79f9ea25942ec8b948..165487339a7c169418e413069c48150f1c92b8ea 100644 (file)
@@ -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
index 448fdd61082e2cd6503fe400ecbf11746cb3a844..b375bb6ba02f4807f0b782da2cf795e61357eded 100644 (file)
@@ -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);
 
index 21d11c969a5ef45ad7f83ebab63f9313f79555ea..f9b32946ae491c6ceb0de6d3bfaa32614a941475 100644 (file)
@@ -48,21 +48,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_basic_write_print_help_
-  extern f_status_t fss_basic_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_basic_write_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -83,7 +68,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fss_basic_write_main_
-  extern f_status_t fss_basic_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_basic_write_main(fll_program_data_t * const main, fss_basic_write_setting_t * const setting);
 #endif // _di_fss_basic_write_main_
 
 #ifdef __cplusplus
index 0c1a9a5bde970413c49bfcfc9cd7e997d5773fb6..c953bc546c7a6e29fbe01e5eac4fca5ce54b971e 100644 (file)
@@ -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 (file)
index 0000000..9cd5a00
--- /dev/null
@@ -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 (file)
index 0000000..99ef649
--- /dev/null
@@ -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
index f3fb15e1b9977bd417297f2bd2f01c46a1d1f413..d1c0ac4f2bdbfcf279796f087988b4ebadb9d7e0 100644 (file)
@@ -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
index 972ecdc7cef3f8662e6301427532b4dde7c06207..c9af8243b528b5bd40d25b277716a03b0d1b9512 100644 (file)
@@ -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
index 9c5c7f3e3908a82978fd378c47368a3bed04edcd..d86cd5feff1bbc61641d3fc7d61b571a4f641262 100644 (file)
@@ -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);
         }
index 12f063769ca0a6cf072f4c5f4a0bd464200cfb60..292c290af5dee0667d09b2d0c9376283731053eb 100644 (file)
@@ -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
index d93b633fc3eab3c4dd0d787f07a887e13e48e5e4..98a5025d747877d19271346f311b12421fc7d734 100644 (file)
@@ -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
index 70f025ad4231c893950d5482424d308786ae66be..bf62570432548b118df7ded435c96eaccca69376 100644 (file)
@@ -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
index 3eb1dba0342d0a09ff54c5f14fae0c1e378b7b5e..e8d476249b0fee3ccbd68d05d6e3bc86ae4cbb62 100644 (file)
@@ -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);
 
index f6e853d6c9764039ae39cfe8ad285a8f83ee1d7b..01450670fe2c8f2be3320f2720a16e129c745886 100644 (file)
@@ -55,21 +55,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_embedded_list_read_print_help_
-  extern f_status_t fss_embedded_list_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_embedded_list_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -82,16 +67,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_embedded_list_read_main_
-  extern f_status_t fss_embedded_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_embedded_list_read_main(fll_program_data_t * const main, fss_embedded_list_read_setting_t * const setting);
 #endif // _di_fss_embedded_list_read_main_
 
 #ifdef __cplusplus
index fa84dae30e653e246a00f97736ca8ecb39ceb600..db1288bc6c72a006de3ad58aaafa2ef6934962d5 100644 (file)
@@ -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 (file)
index 0000000..1311924
--- /dev/null
@@ -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 (file)
index 0000000..4787541
--- /dev/null
@@ -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
index f11d776ba8fbd81936896de0778bdada6d4a3859..ddc05e235a05d64b31534db456190efeddc6bf37 100644 (file)
@@ -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
index 30ef1431a49993ccf9302323c27c06d861054be2..b673ccc6d240c55b5f41e9421abb9e59fd553af1 100644 (file)
@@ -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
index c013d58b191090798438a8977d94649dae03a7c1..3bf2ca371855a3852549584e6842ee9dd2b2b8ca 100644 (file)
@@ -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);
           }
index d00cd4677b52c0939dd68bf90b6e0505570697fd..ef09d6be06edbf33bc424a7a2a4ed5394ceb210c 100644 (file)
@@ -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
index 9a528ee65a91f534b51b4c7d68d139402f5e274e..a31b4b71cc1c22f094b17dfe3123153023d4cda7 100644 (file)
@@ -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
index 6351e65117c5909a597eb02d4f7dba948c5e8559..2e0c4c89c9b9538134931e39fbb29179f3eff5ba 100644 (file)
@@ -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
index ddfb5f1d5f60f11f82d478f6b88e183a4a603ff9..a5bd5327cf50d70a7ede0e48bfcae4293b7361d9 100644 (file)
@@ -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);
 
index 23002ef003eca51121a7993b03671d3639011ae1..4347d39cab1b2a6bb9d1e9fbabb02309eb6a8585 100644 (file)
@@ -48,21 +48,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_embedded_list_write_print_help_
-  extern f_status_t fss_embedded_list_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_embedded_list_write_print_help_
-
-/**
  * Execute main program.
  *
  * Be sure to call fss_embedded_list_write_main_delete() after executing this.
@@ -86,7 +71,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fss_embedded_list_write_main_
-  extern f_status_t fss_embedded_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_embedded_list_write_main(fll_program_data_t * const main, fss_embedded_list_write_setting_t * const setting);
 #endif // _di_fss_embedded_list_write_main_
 
 #ifdef __cplusplus
index bd708bdb85d605d92cda669357b6a5fe9daa5268..501e05252d2268c09266357ccd5f6d580adb5d95 100644 (file)
@@ -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 (file)
index 0000000..bddc7b7
--- /dev/null
@@ -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 (file)
index 0000000..562dfed
--- /dev/null
@@ -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
index 656ffaebc62e6f8512993c0741aafd445317b9be..16c4cbb6d18c45410d811255b3fdd40ea65c696a 100644 (file)
@@ -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
index 569d3ecbad5d7f5e3f2ab007c2d9993ed2760b6f..85df5d0086fd26e77e46560175a878790ac4eb8e 100644 (file)
@@ -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
index 25262416299cf94dcc914a9f0f7092e10b21e06a..3654add0d2ad48c101707beeaae1c577fbec5f1e 100644 (file)
@@ -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);
         }
index ee5cdf493b917f8d37a5cc37e00de9f72c9d5791..2359e055d3bf075d91450d377ec680d4866db021 100644 (file)
@@ -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
index e7fedce0dbabc96ca2ace5ba85d2dd49f256bd9b..1726e8f09a5b9613a3249a55a6ed5989b7146478 100644 (file)
@@ -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
index 59b7d8e72e0096ae9785943815c840bba97d31f4..7360cbf09624395c79b1d165d2bf37e7bbbc56e9 100644 (file)
@@ -294,6 +294,66 @@ extern "C" {
 #endif // _di_fss_extended_list_read_delimit_modes_
 
 /**
+ * Flags used to represent flags passed to the main function.
+ *
+ * fss_extended_list_read_main_flag_*_e:
+ *   - none:          No modes in use.
+ *   - file_from:     Using a specified source file.
+ *   - file_to:       Using a specified destination file.
+ *   - help:          Print help.
+ *   - header:        Enable printing of headers.
+ *   - separate:      Enable printing of separators.
+ *   - strip_invalid: Using strip invalid character mode.
+ *   - verify:        Using verify mode.
+ *   - version:       Print version.
+ */
+#ifndef _di_fss_extended_list_read_main_flag_e_
+  enum {
+    fss_extended_list_read_main_flag_none_e          = 0x0,
+    fss_extended_list_read_main_flag_file_from_e     = 0x1,
+    fss_extended_list_read_main_flag_file_to_e       = 0x2,
+    fss_extended_list_read_main_flag_header_e        = 0x4,
+    fss_extended_list_read_main_flag_help_e          = 0x8,
+    fss_extended_list_read_main_flag_separate_e      = 0x10,
+    fss_extended_list_read_main_flag_strip_invalid_e = 0x20,
+    fss_extended_list_read_main_flag_verify_e        = 0x40,
+    fss_extended_list_read_main_flag_version_e       = 0x80,
+  };
+#endif // _di_fss_extended_list_read_main_flag_e_
+
+/**
+ * The fss extended list read main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * flag: Flags passed to the main function.
+ *
+ * status: The main status code, generally used by the load settings and main functions.
+ *
+ * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not.
+ * line_last:  A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not.
+ */
+#ifndef _di_fss_extended_list_read_setting_t_
+  typedef struct {
+    uint16_t flag;
+
+    f_status_t status;
+
+    f_string_static_t line_first;
+    f_string_static_t line_last;
+  } fss_extended_list_read_setting_t;
+
+  #define fss_extended_list_read_setting_t_initialize \
+    { \
+      fss_extended_list_read_main_flag_none_e, \
+      F_none, \
+      f_string_static_t_initialize, \
+      f_string_static_t_initialize, \
+    }
+#endif // _di_fss_extended_list_read_setting_t_
+
+/**
  * Deallocate main.
  *
  * @param main
@@ -310,6 +370,72 @@ extern "C" {
   extern f_status_t fss_extended_list_read_main_delete(fll_program_data_t *main);
 #endif // _di_fss_extended_list_read_main_delete_
 
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *   This does not alter setting.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fss_extended_list_read_setting_delete_
+  extern f_status_t fss_extended_list_read_setting_delete(fss_extended_list_read_setting_t * const setting);
+#endif // _di_fss_extended_list_read_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately retuns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *
+ *   This alters setting.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_fss_extended_list_read_setting_load_
+  extern void fss_extended_list_read_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting);
+#endif // _di_fss_extended_list_read_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *   This does not alter setting.status.
+ *   All buffers are deallocated.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_fss_extended_list_read_setting_unload_
+  extern f_status_t fss_extended_list_read_setting_unload(fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting);
+#endif // _di_fss_extended_list_read_setting_unload_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 9981c39672586fbbc55ef7e58690848beac3e994..218d78ca0e9de82ff7f2b15d025a210fbdac40d7 100644 (file)
@@ -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);
 
index 847c84596fbbb3cc98368e1e7f8f664521f40bd8..b2b6cc5fdbb55bdf4490e7830ff3cc3af5a6c0e0 100644 (file)
@@ -55,21 +55,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_extended_list_read_print_help_
-  extern f_status_t fss_extended_list_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_extended_list_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -82,16 +67,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_extended_list_read_main_
-  extern f_status_t fss_extended_list_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_extended_list_read_main(fll_program_data_t * const main, fss_extended_list_read_setting_t * const setting);
 #endif // _di_fss_extended_list_read_main_
 
 #ifdef __cplusplus
index 30e46c99039119f2d16afa656a93ade9a2c05320..aff8ca90eabba275e3f91963768e55b5b95dd727 100644 (file)
@@ -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 (file)
index 0000000..893c762
--- /dev/null
@@ -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 (file)
index 0000000..73015d0
--- /dev/null
@@ -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
index 688b59e0fae17c792b0fe5d5a2ab213d26fc32d1..46fcfa1fbc5d83d111036c3469ed447a4f755e95 100644 (file)
@@ -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
index 0dc07c4160955d27c5ba044ad0bab30daf73c484..8bd3c494da272522b294fcc0a26e570b4daa2432 100644 (file)
@@ -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
index 1da5a70d7cd6b06a8015335cc8c809b8d1a56127..3494f4bcce9dcbcaa5bec0760b5cbc96633007d2 100644 (file)
@@ -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);
           }
index 683d0db2f0f72ec14719a037bc256fc309606c02..c67a02ad3ca3fbe45283a25dc56088283b4f7607 100644 (file)
@@ -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
index 4adc3bbfffca2372975a0caaf2db52c367d81f50..ec3991a2142b1aa4eedd814f4792671ec0534370 100644 (file)
@@ -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
index b80105eba393c203a3cb4942d5196809bdbaeee7..2699c8229661ab00e59f37b0617ff6920b572909 100644 (file)
@@ -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
index a82340b2f93aef076456916aa9db20fec8a642d3..4b3c9a67c60e9c2264a087a0f4ec019211ad7267 100644 (file)
@@ -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);
 
index ce18f5b60d0c041926f1ce5cfbd0b5afd86f7aae..64f3df75f2db19e588647d8394cef818226c53e5 100644 (file)
@@ -48,21 +48,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_extended_list_write_print_help_
-  extern f_status_t fss_extended_list_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_extended_list_write_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -75,16 +60,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_extended_list_write_main_
-  extern f_status_t fss_extended_list_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_extended_list_write_main(fll_program_data_t * const main, fss_extended_list_write_setting_t * const setting);
 #endif // _di_fss_extended_list_write_main_
 
 #ifdef __cplusplus
index 6814f7d9270fe9a2a868f17c6704cd47ea740c47..40848bee764c4a7a336c6aaaef724803cb6ecd29 100644 (file)
@@ -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 (file)
index 0000000..0b44a87
--- /dev/null
@@ -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 (file)
index 0000000..9da45b4
--- /dev/null
@@ -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
index 24de2602dfab88713cf9306726d4414701667982..4e3d529db13861ad051e494791193c6dec2cc7d4 100644 (file)
@@ -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
index 891a2ab439ab6336905c1bee6b285cd3c08cc4bf..08cc0999c674551cea92f6232f42a5c38c862487 100644 (file)
@@ -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
index 47e754f7b6b073ec59c4bab34d5a18e8deb982e8..1a44c8d9930e8ce83195124d23ad7a3aec2e26f5 100644 (file)
@@ -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);
         }
index c8ca91170462ae89a5dd5918c5a99264c2376ae3..4d34c0ec65afb1a312d96a78d2ae5fdcca48cb4d 100644 (file)
@@ -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
index 0f44d43541fdc28a6c6b2ca53a7aacbb00107e60..cb20d4340b3e57c5a4360817f6746405a045b161 100644 (file)
@@ -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
index e4a38b6089ffa544af46a300f9aa2a9bc492ea4c..76f31677dd2903b1fe33baf907a92e3378bbf4e4 100644 (file)
@@ -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
index 4226bb8ca52859dcb090a0bc5272bdbaa904e8c1..b64bbfae2027aaad7dec2bdac84ea520bb4fc6b1 100644 (file)
@@ -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);
 
index bbdd1bf07e414987fd91773ee793c89a65a1f28d..9d28801cca9053fd093e70cbe86d61274ec58b26 100644 (file)
@@ -55,21 +55,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_extended_read_print_help_
-  extern f_status_t fss_extended_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_extended_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -91,7 +76,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fss_extended_read_main_
-  extern f_status_t fss_extended_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_extended_read_main(fll_program_data_t * const main, fss_extended_read_setting_t * const setting);
 #endif // _di_fss_extended_read_main_
 
 #ifdef __cplusplus
index 95d7a453c3659cff812dbf73fa491c7417009879..5998ee6159a304f8cdb61297632ea1268a656083 100644 (file)
@@ -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 (file)
index 0000000..c9f770a
--- /dev/null
@@ -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 (file)
index 0000000..7d543dc
--- /dev/null
@@ -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
index 9c7dcb1579c8816856de910bbe9a37f347ec945d..ac6911f4a8703b48f8140407ebe5b6edae450780 100644 (file)
@@ -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
index cbbe68501f0f8cf8ebcfd70baf9e540ebb2f7d8f..a25d20151b2301c443130e23f381980dd1be18e2 100644 (file)
@@ -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
index d4f79509f046238085dd2cd221b654329d6e69f2..fedaa0ed22a9b72df757605235286e34344f18be 100644 (file)
@@ -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);
           }
index 7b6720a8956a5de524c35df2038daff46db3d7fb..42d9f1c9a742d8acde4b9758d436dab705b11ee5 100644 (file)
@@ -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
index 12ecb7265a06b4ae999f3e7345084bb1bf38069d..f4323601f075f209422a89ca66f2858772c47d57 100644 (file)
@@ -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
index 3ba6427dbdae97e502aed65ea8261c49b04e152a..03ba6d0f0f64471d937ad805cd415660111cf843 100644 (file)
@@ -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
index 9ecf12e97bc816b5c79a1375525918d3a4ad0f0c..de6d4b9a204f34f566c175eff5dba42fecb509d4 100644 (file)
@@ -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);
 
index b444dfd30d12294f1b9ea976a743ee12bdcc6756..e1da061a5d10dd19dd40e172a393880a0e091966 100644 (file)
@@ -48,21 +48,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_extended_write_print_help_
-  extern f_status_t fss_extended_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_extended_write_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -75,16 +60,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_extended_write_main_
-  extern f_status_t fss_extended_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_extended_write_main(fll_program_data_t * const main, fss_extended_write_setting_t * const setting);
 #endif // _di_fss_extended_write_main_
 
 #ifdef __cplusplus
index 48d1286f8d83004c8dd89175e3f8f7215c6080ce..c6cc6f3c02f5601c6b5d6a5be6b11eb9c318df77 100644 (file)
@@ -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 (file)
index 0000000..9e5e72f
--- /dev/null
@@ -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 (file)
index 0000000..79dffc5
--- /dev/null
@@ -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
index 2d5b189afd52fe4f018885cbf9cb5b8a60885980..635db9c186e2b2c7747efffede84965aa2a53441 100644 (file)
@@ -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
index a1f81794df3e05aa2ec9cbadd0ae153394a06ff9..d7617beb1df32ec0904af91564589d25bb1481e9 100644 (file)
@@ -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
index a33d943a366c2f5c9d7a4d7c5620f8aa5eb6489c..c1cdbe45053db7fa892c807c43217356c562bc9e 100644 (file)
@@ -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);
 
index 151ed40043705b73e15634e04c96514e571375c6..22315b9fe24e7afc08442213a1f1fff1f6f4898d 100644 (file)
@@ -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
index 2ab2fa7e0201bf706ea76668b4a6877859ac63e4..2e87b1848800595d81cacb6d9c0179acb1572578 100644 (file)
@@ -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
index 38764dd3a4d5b252a32b085d3a118f5f19f8fb12..8fa4c91fd9d002cb99c575c200c4b4e0a7e7fecd 100644 (file)
@@ -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
index f42a1ffdf94afead6aa33d2ff792d6ba91bb0969..f5a07113504c16ac27f0a5e8c8c74f0bff5f2b51 100644 (file)
@@ -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);
 
index 501d1576bd3bbbb256ee1bfdeeb3364ee0b785e0..a7750e6e79f11ef3a272ad750780b8a5305f3942 100644 (file)
@@ -53,21 +53,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_identify_print_help_
-  extern f_status_t fss_identify_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_identify_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -80,16 +65,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_identify_main_
-  extern f_status_t fss_identify_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_identify_main(fll_program_data_t * const main, fss_identify_setting_t * const setting);
 #endif // _di_fss_identify_main_
 
 #ifdef __cplusplus
index 1b697b8020cd67e92425579dd172bc6aeb71383b..5ef29a147a6da842ee4adc02355a4cfdcf986b4a 100644 (file)
@@ -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 (file)
index 0000000..36e102b
--- /dev/null
@@ -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 (file)
index 0000000..437e982
--- /dev/null
@@ -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
index 3d7aba08af88c8577a10cd067ae3bb67953979c5..e6d4b34c02bb76f96e5ea3e44ebcc91361d32a49 100644 (file)
@@ -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
index e584f3676f4b1154724383469290c64f38e587b7..72491fa5b1f3c46db4fbe8fae3e913d920abd760 100644 (file)
@@ -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
index 0441ddb80da498a22e95c6e06feff1542f85d57e..2fa7c040d016e396715da00acfe36a5aea3682ce 100644 (file)
@@ -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);
 
index a016bd40fb619264c7aa27ce395fc72689828101..9797c7cdb95cc4cfb8485d503ee01864d8e0365c 100644 (file)
@@ -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
index 0c742fad0c2e460acc21e537b69fd4c799e249d5..49fdb5d55f82609db372360f9f773ab4660ac69e 100644 (file)
@@ -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
index 186be3c4b8e50fad2413e223186c28b352ca7715..839adb7ba128c1db8694ed7f75ca776fbce6c4cd 100644 (file)
@@ -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
index 01cfa0cf04ffdcd0b3f0ba331ec5989ca33b317b..4b536ae336a03f0d2849b32f4650cfb5d198d9ba 100644 (file)
@@ -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);
 
index 1aaca7ea4e712ef64fed92fa4204fd6724b5a43e..237c49c1a378aefb7622ead5c720c0cce151c953 100644 (file)
@@ -56,21 +56,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_payload_read_print_help_
-  extern f_status_t fss_payload_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_payload_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -92,7 +77,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fss_payload_read_main_
-  extern f_status_t fss_payload_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_payload_read_main(fll_program_data_t * const main, fss_payload_read_setting_t * const setting);
 #endif // _di_fss_payload_read_main_
 
 #ifdef __cplusplus
index c4e4387a7959395d7d7edefbac247c8b909dea2a..1fa6db4cd899c20704e45bc64c25782b48989863 100644 (file)
@@ -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 (file)
index 0000000..5bb4951
--- /dev/null
@@ -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 (file)
index 0000000..5b44116
--- /dev/null
@@ -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
index 7816a6dc4e943e7ad83911825f20f7b78abb9ac2..7ba318340a572a1af182e0711f9dbc61e076bca1 100644 (file)
@@ -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
index c19e859d7496c06fa3fbdc8951c29d646a56b0a9..e52f234594777750a156a62c0f6da4d948fcc20b 100644 (file)
@@ -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
index 36e0da4e49c468a4f76a43d6d003c48640c95afb..d99d35d7d6d181eab5da01e10f35bfd5852e08eb 100644 (file)
@@ -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);
         }
index cb89eb06ff8780c9fdbcafb0bfb9657a0563cca3..94ca06f48a0d5bcbd4df839f208856be0e47209d 100644 (file)
@@ -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
index 6d321da50565dd0df4af100c6ef0c91e9b972a85..84a5dcfd4eb833b496ab117ed3e85360fca78a5f 100644 (file)
@@ -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
index 5f8126f9516b061143b386b97a26f86dfa39c2e4..b9094ebbdf7fdf6070c5098abff7d5e4eaf01220 100644 (file)
@@ -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
index 1cc34ec241a94cf31a9acb03deb0ff456e55cadb..0669bb8cbed62cf74c187624fd80fa1050d0f074 100644 (file)
@@ -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);
 
index da56d81667e456ee6f6d1404a4110b70463f7d49..1f640190c9c108c7c785d6896a931059e0c06919 100644 (file)
@@ -48,21 +48,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_payload_write_print_help_
-  extern f_status_t fss_payload_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_payload_write_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -75,16 +60,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_payload_write_main_
-  extern f_status_t fss_payload_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t fss_payload_write_main(fll_program_data_t * const main, fss_payload_write_setting_t * const setting);
 #endif // _di_fss_payload_write_main_
 
 #ifdef __cplusplus
index 5a9452cf1e11f0743ec88b0e08cd41da6f7c2a5e..e9649899d165b2ae403247b65d8573ab0c3f1cf9 100644 (file)
@@ -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 (file)
index 0000000..91f5ca5
--- /dev/null
@@ -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 (file)
index 0000000..b2fb19a
--- /dev/null
@@ -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
index 87bff8596aa181c82ea7c020420a24cc573d9804..33626b57d547a566290eab851ca1b3c23451bc4c 100644 (file)
@@ -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
index 51b200164334ab839bffadd40eca1ec53e2278d1..1262946859427c72e3b1ea604f4f519a207d04cb 100644 (file)
@@ -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
index 964cc9bfa34f25add8d3774a26ada88e63cc004e..3b93b2abfa04671db3dca8f49125e549be02dfa3 100644 (file)
@@ -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);
 
index 84c0b5ae1ac5f2d7e7df675bbfad7cab8664b0ab..e661405ddfa0ff47f6c13ff8ed247aa2ef7c2ded 100644 (file)
@@ -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
index c6e73aaf8ab39af6945efedd0aec3a554796c967..0d5f5481b840d8d6a55d763a6eccda2b4959d7c2 100644 (file)
@@ -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
index 5f531b766b2f2a98f422c68e42688a2d2df53aaa..690917fb41b11ab8458df5c8c986982138006725 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * FLL - Level 3
  *
- * Project: FSS Status code
+ * Project: FSS Status Code
  * API Version: 0.7
  * Licenses: lgpl-2.1-or-later
  *
@@ -70,6 +70,35 @@ extern "C" {
 #endif // _di_fss_status_code_program_help_parameters_
 
 /**
+ * Special strings used by this program.
+ */
+#ifndef _di_fss_status_code_strings_
+  #define FSS_STATUS_CODE_failed_to_convert_s "failed to convert"
+  #define FSS_STATUS_CODE_invalid_number_s    "invalid number"
+  #define FSS_STATUS_CODE_invalid_name_s      "invalid name"
+  #define FSS_STATUS_CODE_invalid_main_s      "invalid main"
+  #define FSS_STATUS_CODE_out_of_range_s      "out of range"
+  #define FSS_STATUS_CODE_unknown_code_s      "unknown code"
+  #define FSS_STATUS_CODE_unknown_name_s      "unknown name"
+
+  #define FSS_STATUS_CODE_failed_to_convert_s_length 17
+  #define FSS_STATUS_CODE_invalid_number_s_length    14
+  #define FSS_STATUS_CODE_invalid_name_s_length      12
+  #define FSS_STATUS_CODE_invalid_main_s_length      12
+  #define FSS_STATUS_CODE_out_of_range_s_length      12
+  #define FSS_STATUS_CODE_unknown_code_s_length      12
+  #define FSS_STATUS_CODE_unknown_name_s_length      12
+
+  extern const f_string_static_t fss_status_code_failed_to_convert_s;
+  extern const f_string_static_t fss_status_code_invalid_number_s;
+  extern const f_string_static_t fss_status_code_invalid_name_s;
+  extern const f_string_static_t fss_status_code_invalid_main_s;
+  extern const f_string_static_t fss_status_code_out_of_range_s;
+  extern const f_string_static_t fss_status_code_unknown_code_s;
+  extern const f_string_static_t fss_status_code_unknown_name_s;
+#endif // _di_fss_status_code_strings_
+
+/**
  * The program defines.
  */
 #ifndef _di_fss_status_code_defines_
@@ -152,7 +181,131 @@ extern "C" {
     }
 
   #define fss_status_code_total_parameters_d 16
-#endif // _di_fss_status_code_defines_
+#endif // _di_fss_status_code_parameters_
+
+/**
+ * Flags used to represent flags passed to the main function.
+ *
+ * When number mode is not specified, then mode is "string" mode (there is no flag for "string" mode).
+ *
+ * fss_status_code_main_flag_*_e:
+ *   - none:    No modes in use.
+ *   - error:   Check if status is "error".
+ *   - fine:    Check if status is "fine".
+ *   - help:    Print help.
+ *   - number:  Operate in number mode.
+ *   - version: Print version.
+ *   - warning: Check if status is "warning".
+ */
+#ifndef _di_fss_status_code_main_flag_e_
+  enum {
+    fss_status_code_main_flag_none_e    = 0x0,
+    fss_status_code_main_flag_error_e   = 0x1,
+    fss_status_code_main_flag_fine_e    = 0x2,
+    fss_status_code_main_flag_help_e    = 0x4,
+    fss_status_code_main_flag_number_e  = 0x8,
+    fss_status_code_main_flag_version_e = 0x10,
+    fss_status_code_main_flag_warning_e = 0x20,
+  };
+#endif // _di_fss_status_code_main_flag_e_
+
+/**
+ * The status code main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * flag: Flags passed to the main function.
+ *
+ * status: The main status code, generally used by the load settings and main functions.
+ *
+ * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not.
+ * line_last:  A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not.
+ */
+#ifndef _di_fss_status_code_setting_t_
+  typedef struct {
+    uint16_t flag;
+
+    f_status_t status;
+
+    f_string_static_t line_first;
+    f_string_static_t line_last;
+  } fss_status_code_setting_t;
+
+  #define fss_status_code_setting_t_initialize \
+    { \
+      fss_status_code_main_flag_none_e, \
+      F_none, \
+      f_string_static_t_initialize, \
+      f_string_static_t_initialize, \
+    }
+#endif // _di_fss_status_code_setting_t_
+
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *   This does not alter setting.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_fss_status_code_setting_delete_
+  extern f_status_t fss_status_code_setting_delete(fss_status_code_setting_t * const setting);
+#endif // _di_fss_status_code_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately retuns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *
+ *   This alters setting.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_fss_status_code_setting_load_
+  extern void fss_status_code_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, fss_status_code_setting_t * const setting);
+#endif // _di_fss_status_code_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *   This does not alter setting.status.
+ *   All buffers are deallocated.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_fss_status_code_setting_unload_
+  extern f_status_t fss_status_code_setting_unload(fll_program_data_t * const main, fss_status_code_setting_t * const setting);
+#endif // _di_fss_status_code_setting_unload_
 
 #ifdef __cplusplus
 } // extern "C"
index c84f07c1cd8129c4068d41642a8072c6dc25909c..3b580e4f6b99e7656de81c87f24cb9882662bfb3 100644 (file)
 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_
 
index be8a2ce41cec683167776b10b0d80deda78efd9e..e3458dd7150cf0e054cb692a7e4bd4c6f2c85566 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * FLL - Level 3
  *
- * Project: FSS
+ * Project: FSS Status Code
  * API Version: 0.7
  * Licenses: lgpl-2.1-or-later
  *
 
 // FSS Status Code includes.
 #include <program/fss_status_code/common.h>
+#include <program/fss_status_code/print.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_fss_status_code_print_help_
-  extern f_status_t fss_status_code_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_fss_status_code_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -77,16 +63,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_fss_status_code_main_
-  extern f_status_t fss_status_code_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern void fss_status_code_main(fll_program_data_t * const main, fss_status_code_setting_t * const setting);
 #endif // _di_fss_status_code_main_
 
 #ifdef __cplusplus
index 3cff8f6899f3aa5dbd242f66d9b9bff4e2f9bc50..1f56485d2bbf83dc3609b5411dd06f14147731bc 100644 (file)
@@ -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 (file)
index 0000000..f0d58a2
--- /dev/null
@@ -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 (file)
index 0000000..cca7957
--- /dev/null
@@ -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
index ed96d23a1f90e975854d0de7a61a6aba16581f3c..24a88a74b6eb1e502a7e583fb9168c0b6dc5a5b3 100644 (file)
@@ -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
index 7e8029c47c0a7afca3321e4af5d0077c09d4228e..53a416ea17b45230e603993f0dd359cd42565d79 100644 (file)
 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
index 7ee3d6c49cbfb769d9f1b893417bcf1c3112d21b..77147b8b6fd4ac0db4a8f8cb5989333759048984 100644 (file)
@@ -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;
index 182c93d3c492bd5f2c54a79b5d663a7db40a5b8d..56a600b9a040ad24af0a96d5fb8b36843c62d7a0 100644 (file)
@@ -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
index 703e58072dbbad9e5b846aeb279c248acf9297bd..f223e895812b29b3919b0561be002176f8ef4900 100644 (file)
@@ -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
index 00af88241dab815f0c5cefc55607101c77cc752e..a0ccf6097963a768487b40c3f123ba70d9239879 100644 (file)
@@ -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
index 945aa8bd81442b7044b8d605cb8df2c60313a83d..70f25e09287019228856e33e5a32cbdfe40761c5 100644 (file)
@@ -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
index 927eea770f5f63c8651fb8c2cfac200511145cfe..3b03fb6cf172abf712099ef14c33b15884b358a0 100644 (file)
@@ -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);
 
index 79d0f5f385a86821afdfcf674079cd5c9805853c..d26c134eb9ddc81e269a4f6c085e8ceb3d38f41c 100644 (file)
@@ -58,21 +58,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_iki_read_print_help_
-  extern f_status_t iki_read_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_iki_read_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -85,16 +70,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_iki_read_main_
-  extern f_status_t iki_read_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t iki_read_main(fll_program_data_t * const main, iki_read_setting_t * const setting);
 #endif // _di_iki_read_main_
 
 #ifdef __cplusplus
index 56ed1be02fb5c6f98696680f56739bb739545d61..87d88e417dda058b5c2002a6a2162cf1d9a06ee6 100644 (file)
@@ -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 (file)
index 0000000..e901ed1
--- /dev/null
@@ -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 (file)
index 0000000..9afe978
--- /dev/null
@@ -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
index 3173b73f497ba84b8f114aa16e2f77f286ec9285..6d208abcf016c0bf72c4f268a15812630a988b48 100644 (file)
@@ -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
index 471afccb45b0c07a7af9d5544d00940d89a29351..3039b9a4e60d5093bf58e29bbd1f1b81c7263c32 100644 (file)
@@ -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
index 1848ff64ad398b86485f5d628790f9bcd07ff57f..c4f81a26ee9eb2a220432b9b8edb7e0f7732bd71 100644 (file)
@@ -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;
index 4c8ec6aae96d8d762167537399a4060f8f24059f..99332ffd7dd69dd20a57577823635dcb917bff7a 100644 (file)
@@ -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
index 79b2b32d0710aee4d0da9554f7cbfb2e0e455c3f..3f91b7f00dc59ef7ff4746ceb2acdc01816d5dd1 100644 (file)
@@ -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);
 
index 84a2dd07b6341e2c6079066d939ca4689a256cc2..f41b1df5c468e86ceb071960bc456985c9b17a25 100644 (file)
@@ -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_
 
 /**
index f3e93fd0922f91d6b7baa5ee589d92263e02a925..b7341863209e6e1ab58d4846279a0cef60a3ee15 100644 (file)
@@ -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
index 95d8b88437f4f7d63212ae7b42c6d63f5956612f..993dc44dd5cdbd59f34cbfa95f05fd11a9cbefcb 100644 (file)
@@ -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
index c2562cecf06a59bebb7e84556cb25fe220806596..0da4da3cc3514660805644abb1a2c6da82cd6974 100644 (file)
@@ -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
index 2497a3cb5a3a40f9e93eaa24ba01b96dd8c75fcd..c265da3abbb5e27d1603166aa164d5f843bf8ccb 100644 (file)
@@ -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);
     }
 
index 58fab705b460fb17a1c97b5a43cd00fa4a66d5b6..325155061ede24f0a2a5405256d8c2fa8d9e2138 100644 (file)
@@ -58,21 +58,6 @@ extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_iki_write_print_help_
-  extern f_status_t iki_write_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_iki_write_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -85,16 +70,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_iki_write_main_
-  extern f_status_t iki_write_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern f_status_t iki_write_main(fll_program_data_t * const main, iki_write_setting_t * const setting);
 #endif // _di_iki_write_main_
 
 #ifdef __cplusplus
index f6b68d1fd9696d0075ba95197cd0df9637464acf..fa672df4df22c9de07482cfb3db8dad0fd77aced 100644 (file)
@@ -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 (file)
index 0000000..0249187
--- /dev/null
@@ -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 (file)
index 0000000..7d27db1
--- /dev/null
@@ -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
index 5168e724c855cd981617c109535619cd9e0a5237..a14b2d90714a28b4416ea9c0cd9ea9a2fa12afe9 100644 (file)
@@ -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
index 5ec92d6160d477f26611af7d920b2b7571956583..54c09450d31c15206adff5ef7b7851e105b56933 100644 (file)
@@ -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
index 0cc2b77dd0c2b22b6bdb57cbefadb27284556f99..8e5db8f38427ebe5ee2b6c544277e63f964c2a2d 100644 (file)
@@ -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) {
index a778a1885fcad371fb371883c91347bb0280248c..1743b9b88cd16c73a6ec9d8b33a8be3a2b053221 100644 (file)
@@ -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
index 4f280213e338c2131699df5c61fca4d3110fa115..801023a31f0f5db292a9d036752dd39d47adf5b6 100644 (file)
@@ -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
index abccb6dcf8d782f277c0ce09298f593551353472..f6466066bf20bdb803588d2fac362a2d62b9a3fd 100644 (file)
@@ -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
index 1d77a4b7905b533004f0948837ade039b9cd7ae0..30305319b2828e78f246a25b9fbafe06c3f22243 100644 (file)
@@ -70,6 +70,35 @@ extern "C" {
 #endif // _di_status_code_program_help_parameters_
 
 /**
+ * Special strings used by this program.
+ */
+#ifndef _di_status_code_strings_
+  #define STATUS_CODE_failed_to_convert_s "failed to convert"
+  #define STATUS_CODE_invalid_number_s    "invalid number"
+  #define STATUS_CODE_invalid_name_s      "invalid name"
+  #define STATUS_CODE_invalid_main_s      "invalid main"
+  #define STATUS_CODE_out_of_range_s      "out of range"
+  #define STATUS_CODE_unknown_code_s      "unknown code"
+  #define STATUS_CODE_unknown_name_s      "unknown name"
+
+  #define STATUS_CODE_failed_to_convert_s_length 17
+  #define STATUS_CODE_invalid_number_s_length    14
+  #define STATUS_CODE_invalid_name_s_length      12
+  #define STATUS_CODE_invalid_main_s_length      12
+  #define STATUS_CODE_out_of_range_s_length      12
+  #define STATUS_CODE_unknown_code_s_length      12
+  #define STATUS_CODE_unknown_name_s_length      12
+
+  extern const f_string_static_t status_code_failed_to_convert_s;
+  extern const f_string_static_t status_code_invalid_number_s;
+  extern const f_string_static_t status_code_invalid_name_s;
+  extern const f_string_static_t status_code_invalid_main_s;
+  extern const f_string_static_t status_code_out_of_range_s;
+  extern const f_string_static_t status_code_unknown_code_s;
+  extern const f_string_static_t status_code_unknown_name_s;
+#endif // _di_status_code_strings_
+
+/**
  * The program defines.
  */
 #ifndef _di_status_code_defines_
@@ -154,6 +183,130 @@ extern "C" {
   #define status_code_total_parameters_d 16
 #endif // _di_status_code_parameters_
 
+/**
+ * Flags used to represent flags passed to the main function.
+ *
+ * When number mode is not specified, then mode is "string" mode (there is no flag for "string" mode).
+ *
+ * status_code_main_flag_*_e:
+ *   - none:    No modes in use.
+ *   - error:   Check if status is "error".
+ *   - fine:    Check if status is "fine".
+ *   - help:    Print help.
+ *   - number:  Operate in number mode.
+ *   - version: Print version.
+ *   - warning: Check if status is "warning".
+ */
+#ifndef _di_status_code_main_flag_e_
+  enum {
+    status_code_main_flag_none_e    = 0x0,
+    status_code_main_flag_error_e   = 0x1,
+    status_code_main_flag_fine_e    = 0x2,
+    status_code_main_flag_help_e    = 0x4,
+    status_code_main_flag_number_e  = 0x8,
+    status_code_main_flag_version_e = 0x10,
+    status_code_main_flag_warning_e = 0x20,
+  };
+#endif // _di_status_code_main_flag_e_
+
+/**
+ * The status code main program settings.
+ *
+ * This is passed to the program-specific main entry point to designate program settings.
+ * These program settings are often processed from the program arguments (often called the command line arguments).
+ *
+ * flag: Flags passed to the main function.
+ *
+ * status: The main status code, generally used by the load settings and main functions.
+ *
+ * line_first: A string expected to represent either "\n" or NULL to allow for easy handling of when to print first new line or not.
+ * line_last:  A string expected to represent either "\n" or NULL to allow for easy handling of when to print last new line or not.
+ */
+#ifndef _di_status_code_setting_t_
+  typedef struct {
+    uint16_t flag;
+
+    f_status_t status;
+
+    f_string_static_t line_first;
+    f_string_static_t line_last;
+  } status_code_setting_t;
+
+  #define status_code_setting_t_initialize \
+    { \
+      status_code_main_flag_none_e, \
+      F_none, \
+      f_string_static_t_initialize, \
+      f_string_static_t_initialize, \
+    }
+#endif // _di_status_code_setting_t_
+
+/**
+ * Delete the program main setting data.
+ *
+ * @param setting
+ *   The program main setting data.
+ *   This does not alter setting.status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ */
+#ifndef _di_status_code_setting_delete_
+  extern f_status_t status_code_setting_delete(status_code_setting_t * const setting);
+#endif // _di_status_code_setting_delete_
+
+/**
+ * Perform the standard program setting load process.
+ *
+ * This prints error messages as appropriate.
+ *
+ * If either main or setting is NULL, then this immediately retuns without doing anything.
+ *
+ * @param arguments
+ *   The parameters passed to the process (often referred to as command line arguments).
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *
+ *   This alters setting.status:
+ *     F_none on success.
+ *
+ *     Errors (with error bit) from: f_console_parameter_process().
+ *     Errors (with error bit) from: fll_program_parameter_process_context().
+ *
+ * @see f_console_parameter_process()
+ * @see fll_program_parameter_process_context()
+ */
+#ifndef _di_status_code_setting_load_
+  extern void status_code_setting_load(const f_console_arguments_t arguments, fll_program_data_t * const main, status_code_setting_t * const setting);
+#endif // _di_status_code_setting_load_
+
+/**
+ * Perform the standard program setting unload process.
+ *
+ * @param main
+ *   The main program data.
+ * @param setting
+ *   The main program settings.
+ *   This does not alter setting.status.
+ *   All buffers are deallocated.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: utf8_setting_delete().
+ *
+ * @see utf8_setting_delete()
+ */
+#ifndef _di_status_code_setting_unload_
+  extern f_status_t status_code_setting_unload(fll_program_data_t * const main, status_code_setting_t * const setting);
+#endif // _di_status_code_setting_unload_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 98802168b84be894f2eb8d6d456efa18a5fdd9aa..5c7ac19ffd0fbecf756e5625b3274b39cbe06a5e 100644 (file)
@@ -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 (file)
index 0000000..d28b8b1
--- /dev/null
@@ -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 (file)
index 0000000..e541062
--- /dev/null
@@ -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
index 1ee3c476bdb57b92914522b89b7dba2e3e2bfa34..7540b79d0cb01c1393604db98794a1b6cf6d449d 100644 (file)
@@ -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
index 6a1589dff3faf88a9b13c1368da93d5ba53f13fd..dc1d6a4e265b4400fccf159ffa91639411149714 100644 (file)
 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
index 5054717d9421531e89c9a28d2eaf7f0edb216766..24684d3f2fda1867194dac2b2596c6e0bcdc7f01 100644 (file)
@@ -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;
index acfa72cc7700985766381ce45b44a589700ec29c..889ea70e8ce72ce50a6a57a38b5478dc7f47721c 100644 (file)
@@ -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
index 620d0e8d3d3b38df131b5a22d6c5b339c1fb7c56..94fe552f8e9cbbc95eea5674da1073afad3c72d0 100644 (file)
 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_
 
index a03e99bd313fd5ded73cd3f5ee2057e9bf2b6246..d4fd0f2ebaa4f78c7830e2df8fc0defd986636ef 100644 (file)
 
 // Status Code includes.
 #include <program/status_code/common.h>
+#include <program/status_code/print.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * Print help.
- *
- * @param file
- *   The file to print to.
- * @param context
- *   The color context settings.
- *
- * @return
- *   F_none on success.
- */
-#ifndef _di_status_code_print_help_
-  extern f_status_t status_code_print_help(const f_file_t file, const f_color_context_t context);
-#endif // _di_status_code_print_help_
-
-/**
  * Execute main program.
  *
  * If main.signal is non-zero, then this blocks and handles the following signals:
@@ -76,16 +62,19 @@ extern "C" {
  *
  * @param main
  *   The main program data.
- * @param arguments
- *   The parameters passed to the process.
+ * @param setting
+ *   The main program settings.
  *
- * @return
- *   F_none on success.
+ *   This alters setting.status:
+ *     F_none on success.
+ *     F_true on success when performing verification and verify passed.
+ *     F_false on success when performing verification and verify failed.
+ *     F_interrupt on (exit) signal received.
  *
- *   Status codes (with error bit) are returned on any problem.
+ *     F_parameter (with error bit) if main is NULL or setting is NULL.
  */
 #ifndef _di_status_code_main_
-  extern f_status_t status_code_main(fll_program_data_t * const main, const f_console_arguments_t arguments);
+  extern void status_code_main(fll_program_data_t * const main, status_code_setting_t * const setting);
 #endif // _di_status_code_main_
 
 #ifdef __cplusplus
index 2c0d018c05d0f7d378491b782b2f82192cde39da..d4692cff5caa655e1355a4a1c04aa454c18329e8 100644 (file)
@@ -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
index e106a7d38a2c9605303058da43d6e4f56a1813b9..1555f6bd7ecaaddec4d9267c982da76cb49e6fbc 100644 (file)
@@ -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;
   }
index 66b55448a00d3ab5a625d733a77d94a4f7d33934..8fe80085f9fb80c8bc5c9b9316be244735b90d20 100644 (file)
@@ -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);
index ae3f2f32cb4a86abd0d88b48d8b14df25e785dcf..71e6c6d07dcdcac261fb64d78085e4598f7afc7f 100644 (file)
@@ -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;
 }
index f00e61693acba6158d3e443e4b8b0e6e4648c39e..5e87a364163aaa12bf8ca61acee55d43f76fe159 100644 (file)
@@ -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) {
 
index 21da76cd8cd2d80f3fcd34825e4d18cc2c725605..c02b5e3f8e96a7d4e7675ee35f00f15b974745d2 100644 (file)
@@ -229,18 +229,14 @@ extern "C" {
  * @param setting
  *   The main program settings.
  *   This does not alter setting.status.
- * @param output
- *   The file to print to.
- * @param context
- *   The color context settings.
+ * @param print
+ *   The output structure to print to.
  *
  * @return
  *   F_none on success.
- *   F_true on success and validation passed.
- *   F_false on success and validation failed.
  */
 #ifndef _di_utf8_print_help_
-  extern f_status_t utf8_print_help(utf8_setting_t * const setting, const f_file_t output, const f_color_context_t context);
+  extern f_status_t utf8_print_help(utf8_setting_t * const setting, const fl_print_t print);
 #endif // _di_utf8_print_help_
 
 /**
@@ -252,7 +248,7 @@ extern "C" {
  *   The main program settings.
  *   This does not alter setting.status.
  * @param print
- *   Designates how the how and where to print.
+ *   Designates the how and where to print.
  * @param lock
  *   If TRUE, then lock the stream.
  *   If FALSE, then do not lock or unlock the stream.
@@ -270,7 +266,7 @@ extern "C" {
  *   The main program settings.
  *   This does not alter setting.status.
  * @param print
- *   Designates how the how and where to print.
+ *   Designates the how and where to print.
  * @param lock
  *   If TRUE, then lock the stream.
  *   If FALSE, then do not lock or unlock the stream.
@@ -380,22 +376,6 @@ extern "C" {
 #endif // _di_utf8_print_section_header_pipe_
 
 /**
- * Print a message about a process signal being recieved, such as an interrupt signal.
- *
- * @param main
- *   The main program data.
- * @param setting
- *   The main program settings.
- *
- *   Assumed to always be non-NULL.
- * @param signal
- *   The signal code received.
- */
-#ifndef _di_utf8_print_signal_received_
-  extern void utf8_print_signal_received(fll_program_data_t * const main, utf8_setting_t * const setting, const f_status_t signal);
-#endif // _di_utf8_print_signal_received_
-
-/**
  * Print the width of the given character.
  *
  * @param main
index d7fbb0d3b0de7380e1a55b9f762406bc7f479f1a..f62a891eb0bd3d6c1b26486e77e028d6b0f90a37 100644 (file)
@@ -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);
 
index 6f454ce89992842c91e939eb33a4413137cedb43..fd5555048aee568ad9fc62df1f60d7fc82e43f23 100644 (file)
@@ -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;
 
index ddf0956d2b062cca2294553f37482fa8d9ca505b..29cc93014970fb85c8f5359f2d3715686fbe9ddd 100644 (file)
@@ -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;
 
index ad93caeb5c74bb0f7951e4bbf498a93d051d8112..9dfc146bde453cca2b169e2444d84cc358916382 100644 (file)
@@ -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;
     }