From fd497ab226c2d50c688d9ce748b918f52ab7d3c3 Mon Sep 17 00:00:00 2001 From: kilo52 Date: Wed, 28 Jan 2026 19:04:38 +0100 Subject: [PATCH 1/4] Added --stop-on-error CLI option. Added an option to stop the process as soon as the first error is encountered. Without the option, some errors might get ignored. For example, when a source file contains syntax errors and thus the logical line count cannot be computed, the scount will skip that file and continue normally with the rest of the files to process. With the --stop-on-error option specified on the command-line, the process stops when the file with a syntax error is encountered and the processed RcnCountStatistics struct is flagged as erroneous. Renamed the files inside the 'mixedWithSyntaxError' test resource directory to have the erroneous source files placed in the middle, as scanned files are always sorted by libreckon. Adjusted other tests accordingly. Changed internal count() implementation in libreckon to copy the erroneous state to the RcnCountStatistics struct being processed so that it is available to the caller. Signed-off-by: kilo52 --- man/scount.1 | 5 +++++ src/lib/c/statistics.c | 4 ++++ src/scount/c/arguments.c | 6 +++++- src/scount/c/scount.h | 1 + src/scount/c/statistics.c | 5 ++++- .../res/expected/mixedWithSyntaxError.txt | 4 ++-- .../{CorrectFile.java => 01_CorrectFile.java} | 0 .../{has_syntax_error.c => 02_has_syntax_error.c} | 0 .../{correct_file.txt => 03_correct_file.txt} | 0 src/scount/tests/functionality/sh/test_scount.sh | 10 +++++++++- 10 files changed, 30 insertions(+), 5 deletions(-) rename src/scount/tests/functionality/res/mixedWithSyntaxError/{CorrectFile.java => 01_CorrectFile.java} (100%) rename src/scount/tests/functionality/res/mixedWithSyntaxError/{has_syntax_error.c => 02_has_syntax_error.c} (100%) rename src/scount/tests/functionality/res/mixedWithSyntaxError/{correct_file.txt => 03_correct_file.txt} (100%) diff --git a/man/scount.1 b/man/scount.1 index 9583dde..9f9360b 100644 --- a/man/scount.1 +++ b/man/scount.1 @@ -5,6 +5,7 @@ scount \- A tool to count logical lines of code and other metrics .B scount [\fB\-\-verbose\fR] [\fB\-\-annotate\-counts\fR] +[\fB\-\-stop\-on\-error\fR] .I .SH DESCRIPTION scount counts source code lines in a single file @@ -43,6 +44,10 @@ Mark counted logical lines and output the result. .br This option can only be used on a single file input. .TP +.B \-\-stop\-on\-error +Stop the processing on the first encountered error, +even for non\-critical errors. +.TP .B \-\-verbose Enable verbose output. .TP diff --git a/src/lib/c/statistics.c b/src/lib/c/statistics.c index ba5e8df..48aeb58 100644 --- a/src/lib/c/statistics.c +++ b/src/lib/c/statistics.c @@ -272,6 +272,10 @@ static inline bool count( if (!options.keepFileContent) { freeSourceFileContent(file); } + if (!ok && options.stopOnError) { + stats->state = result->state; + stats->state.ok = false; + } RCN_LOG_DBG("Done processing file:") RCN_LOG_DBG(file->path) diff --git a/src/scount/c/arguments.c b/src/scount/c/arguments.c index a8ef01f..7edf811 100644 --- a/src/scount/c/arguments.c +++ b/src/scount/c/arguments.c @@ -28,6 +28,8 @@ AppArgs parseArgs(int argc, char** argv) { for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--annotate-counts") == 0) { args.annotateCounts = true; + } else if (strcmp(argv[i], "--stop-on-error") == 0) { + args.stopOnError = true; } else if (strcmp(argv[i], "--verbose") == 0) { args.verbose = true; } else if (strcmp(argv[i], "--help") == 0 @@ -58,7 +60,7 @@ AppArgs parseArgs(int argc, char** argv) { } void showUsage(void) { - logI("Usage: scount [--verbose] [--annotate-counts] "); + logI("Usage: scount [--verbose] [--annotate-counts] [--stop-on-error] "); } void showVersion(AppArgs args) { @@ -95,6 +97,8 @@ void showHelpText(void) { logI(" [--annotate-counts] Mark counted logical lines and output the result."); logI(" This option can only be used on a single file input."); logI(" "); + logI(" [--stop-on-error] Stop processing on first error."); + logI(" "); logI(" [--verbose] Enable verbose output."); logI(" "); logI(" [-#|--version] Show program version information."); diff --git a/src/scount/c/scount.h b/src/scount/c/scount.h index 44c0248..c6defb7 100644 --- a/src/scount/c/scount.h +++ b/src/scount/c/scount.h @@ -50,6 +50,7 @@ typedef struct AppArgs { char* errorMessage; // Error message in case of invalid input int indexUnknown; // Index into `argv` when unknown arg found, or zero bool annotateCounts; // Option: `--annotate-counts` + bool stopOnError; // Option: `--stop-on-error` bool verbose; // Option: `--verbose` bool version; // Option: `-#|--version` bool versionShort; // Option: `-#` diff --git a/src/scount/c/statistics.c b/src/scount/c/statistics.c index 36a7d9e..6515f6c 100644 --- a/src/scount/c/statistics.c +++ b/src/scount/c/statistics.c @@ -97,7 +97,10 @@ ExitStatus outputStatistics(AppArgs args) { reportInputVerbose(path, stats); } - RcnStatOptions options = {0}; + RcnStatOptions options = { + .stopOnError = args.stopOnError + }; + rcnCount(stats, options); const RcnErrorCode errorCode = stats->state.errorCode; diff --git a/src/scount/tests/functionality/res/expected/mixedWithSyntaxError.txt b/src/scount/tests/functionality/res/expected/mixedWithSyntaxError.txt index 34dcb42..9b8610c 100644 --- a/src/scount/tests/functionality/res/expected/mixedWithSyntaxError.txt +++ b/src/scount/tests/functionality/res/expected/mixedWithSyntaxError.txt @@ -2,8 +2,8 @@ Directory: mixedWithSyntaxError Scanned files: 3 o---------- File ----------o--- LLC ---o--- PHL ---o--- WRD ---o--- CHR ---o--- SZE ---o - | CorrectFile.java | 5 | 12 | 33 | 273 | 273 | - | correct_file.txt | 0 | 1 | 20 | 109 | 109 | + | 01_CorrectFile.java | 5 | 12 | 33 | 273 | 273 | + | 03_correct_file.txt | 0 | 1 | 20 | 109 | 109 | o--------------------------o-----------o-----------o-----------o-----------o-----------o Summary: diff --git a/src/scount/tests/functionality/res/mixedWithSyntaxError/CorrectFile.java b/src/scount/tests/functionality/res/mixedWithSyntaxError/01_CorrectFile.java similarity index 100% rename from src/scount/tests/functionality/res/mixedWithSyntaxError/CorrectFile.java rename to src/scount/tests/functionality/res/mixedWithSyntaxError/01_CorrectFile.java diff --git a/src/scount/tests/functionality/res/mixedWithSyntaxError/has_syntax_error.c b/src/scount/tests/functionality/res/mixedWithSyntaxError/02_has_syntax_error.c similarity index 100% rename from src/scount/tests/functionality/res/mixedWithSyntaxError/has_syntax_error.c rename to src/scount/tests/functionality/res/mixedWithSyntaxError/02_has_syntax_error.c diff --git a/src/scount/tests/functionality/res/mixedWithSyntaxError/correct_file.txt b/src/scount/tests/functionality/res/mixedWithSyntaxError/03_correct_file.txt similarity index 100% rename from src/scount/tests/functionality/res/mixedWithSyntaxError/correct_file.txt rename to src/scount/tests/functionality/res/mixedWithSyntaxError/03_correct_file.txt diff --git a/src/scount/tests/functionality/sh/test_scount.sh b/src/scount/tests/functionality/sh/test_scount.sh index a85a0a3..1e7a12f 100644 --- a/src/scount/tests/functionality/sh/test_scount.sh +++ b/src/scount/tests/functionality/sh/test_scount.sh @@ -125,7 +125,7 @@ function test_scount_with_directory_that_contains_file_with_syntax_error() { } function test_scount_with_file_that_has_syntax_error() { - local file="${TEST_RES_DIR}/mixedWithSyntaxError/has_syntax_error.c"; + local file="${TEST_RES_DIR}/mixedWithSyntaxError/02_has_syntax_error.c"; run_app "$file"; assert_exit_status $EXIT_INVALID_INPUT; assert_stdout_is_empty; @@ -133,3 +133,11 @@ function test_scount_with_file_that_has_syntax_error() { assert_stderr_contains "${file}"; assert_stderr_contains "Syntax error detected in source code (0x04)"; } + +function test_scount_with_stop_on_error_option() { + run_app --stop-on-error "${TEST_RES_DIR}/mixedWithSyntaxError"; + assert_exit_status $EXIT_INVALID_INPUT; + assert_stdout_is_empty; + assert_stderr_contains "An error has occurred"; + assert_stderr_contains "Syntax error detected in source code"; +} From 64f851f5803a4b8c998394c348cd8e2c71a636b2 Mon Sep 17 00:00:00 2001 From: kilo52 Date: Thu, 29 Jan 2026 13:40:08 +0100 Subject: [PATCH 2/4] Improved documentation for CLI option. Signed-off-by: kilo52 --- man/scount.1 | 4 +++- src/scount/c/arguments.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/man/scount.1 b/man/scount.1 index 9f9360b..c65f4aa 100644 --- a/man/scount.1 +++ b/man/scount.1 @@ -46,7 +46,9 @@ This option can only be used on a single file input. .TP .B \-\-stop\-on\-error Stop the processing on the first encountered error, -even for non\-critical errors. +even for non\-critical errors. Without this option (the default), +some errors are considered non-critical, in which case the corresponding +file is skipped and the processing continues. .TP .B \-\-verbose Enable verbose output. diff --git a/src/scount/c/arguments.c b/src/scount/c/arguments.c index 7edf811..a3aec35 100644 --- a/src/scount/c/arguments.c +++ b/src/scount/c/arguments.c @@ -97,7 +97,7 @@ void showHelpText(void) { logI(" [--annotate-counts] Mark counted logical lines and output the result."); logI(" This option can only be used on a single file input."); logI(" "); - logI(" [--stop-on-error] Stop processing on first error."); + logI(" [--stop-on-error] Stop processing immediately when an error is encountered."); logI(" "); logI(" [--verbose] Enable verbose output."); logI(" "); From 4b7f2e459459a987f40f004be8a0aeaa0442755c Mon Sep 17 00:00:00 2001 From: kilo52 Date: Thu, 29 Jan 2026 13:48:35 +0100 Subject: [PATCH 3/4] Added test for --stop-on-error option with successful result. Signed-off-by: kilo52 --- src/scount/tests/functionality/sh/test_scount.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/scount/tests/functionality/sh/test_scount.sh b/src/scount/tests/functionality/sh/test_scount.sh index 1e7a12f..e235fcb 100644 --- a/src/scount/tests/functionality/sh/test_scount.sh +++ b/src/scount/tests/functionality/sh/test_scount.sh @@ -141,3 +141,10 @@ function test_scount_with_stop_on_error_option() { assert_stderr_contains "An error has occurred"; assert_stderr_contains "Syntax error detected in source code"; } + +function test_scount_with_ok_directory_input_and_stop_on_error_option() { + run_app --stop-on-error "${TEST_PROJECT_DIR}/src/lib/tests/res/java"; + assert_exit_status $EXIT_SUCCESS; + assert_stdout_equals_file "expected/output_multiple_files.txt"; + assert_stderr_is_empty; +} From d1853e915ca916ef381af583fa89e7efe689700f Mon Sep 17 00:00:00 2001 From: kilo52 Date: Fri, 30 Jan 2026 14:31:29 +0100 Subject: [PATCH 4/4] Renamed functionality test function. Signed-off-by: kilo52 --- src/scount/tests/functionality/sh/test_scount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scount/tests/functionality/sh/test_scount.sh b/src/scount/tests/functionality/sh/test_scount.sh index e235fcb..37acfb8 100644 --- a/src/scount/tests/functionality/sh/test_scount.sh +++ b/src/scount/tests/functionality/sh/test_scount.sh @@ -142,7 +142,7 @@ function test_scount_with_stop_on_error_option() { assert_stderr_contains "Syntax error detected in source code"; } -function test_scount_with_ok_directory_input_and_stop_on_error_option() { +function test_scount_with_valid_directory_input_and_stop_on_error_option() { run_app --stop-on-error "${TEST_PROJECT_DIR}/src/lib/tests/res/java"; assert_exit_status $EXIT_SUCCESS; assert_stdout_equals_file "expected/output_multiple_files.txt";