implement -d option (issue #489) and various improvements default tip

Mon, 07 Apr 2025 20:43:52 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 07 Apr 2025 20:43:52 +0200
changeset 79
e4592d0292e7
parent 78
b3d267334140

implement -d option (issue #489) and various improvements

fixes #636
resolves #638

src/Makefile file | annotate | diff | comparison | revisions
src/cline.c file | annotate | diff | comparison | revisions
src/cline.h file | annotate | diff | comparison | revisions
src/scanner.c file | annotate | diff | comparison | revisions
src/settings.c file | annotate | diff | comparison | revisions
src/settings.h file | annotate | diff | comparison | revisions
src/stdinc.h file | annotate | diff | comparison | revisions
vs/cline.vcxproj file | annotate | diff | comparison | revisions
vs/cline.vcxproj.filters file | annotate | diff | comparison | revisions
--- a/src/Makefile	Sun Nov 10 14:06:03 2024 +0100
+++ b/src/Makefile	Mon Apr 07 20:43:52 2025 +0200
@@ -50,7 +50,7 @@
 	echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
-$(BUILD_DIR)/cline.o: cline.c cline.h stdinc.h settings.h string_list.h \
+$(BUILD_DIR)/cline.o: cline.c stdinc.h settings.h string_list.h \
  bfile_heuristics.h regex_parser.h scanner.h arguments.h
 	echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
--- a/src/cline.c	Sun Nov 10 14:06:03 2024 +0100
+++ b/src/cline.c	Mon Apr 07 20:43:52 2025 +0200
@@ -1,5 +1,5 @@
 /*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  * Copyright 2018 Mike Becker. All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -24,13 +24,17 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "cline.h"
+#ifndef VERSION
+#error "VERSION macro must be set by build system"
+#endif
+
+#include "stdinc.h"
+#include "settings.h"
 #include "scanner.h"
-#include "settings.h"
 #include "arguments.h"
 #include "regex_parser.h"
 
-void printHelpText() {
+static void printHelpText() {
   printf(
     "\nUsage:"
     "\n      cline [Options] [Directories...]"
@@ -40,6 +44,7 @@
     "\n  -b <level>          - binary file heuristics level (default medium)"
     "\n                        One of: ignore low medium high"
     "\n  -c                  - Count non-whitespace characters instead of lines"
+    "\n  -d                  - Report only directory sums"
     "\n  -E <pattern>        - Excludes any line matching the <pattern>"
     "\n  -e <start> <end>    - Excludes lines between <start> and <end>"
     "\n                        You may use these options multiple times"
@@ -74,19 +79,22 @@
     "\n");
 }
 
-int exit_with_version(settings_t* settings) {
+static int exit_with_version(settings_t* settings) {
   printf("cline - Version: " VERSION "\n");
   destroy_settings_t(settings);
   return 0;
 }
 
-int exit_with_help(settings_t* settings, int code) {
+static int exit_with_help(settings_t* settings, int code) {
   printf("cline - Version: " VERSION "\n");
   printHelpText();
   destroy_settings_t(settings);
   return code;
 }
 
+static const char * sepline_double = "===============================================================================\n";
+static const char * sepline_single = "-------------------------------------------------------------------------------\n";
+
 int main(int argc, char** argv) {
 
   /* Settings */
@@ -108,7 +116,7 @@
 
   for (int t = 1 ; t < argc ; t++) {
 
-    int argflags = checkArgument(argv[t], "hsSrRmvVbeEic");
+    int argflags = checkArgument(argv[t], "hsSrRmvVbeEicd");
     int paropt = 0;
 
     /* h */
@@ -203,11 +211,12 @@
     /* i */
     if ((argflags & 2048) > 0) {
       /* cannot be used together with -V */
-      if (registerArgument(&checked, 128)) {
+      if ((checked & 128) > 0) {
         return exit_with_help(settings, 1);
       }
       settings->individual_sums = true;
     }
+    /* c */
     if ((argflags & 4096) > 0) {
         if (registerArgument(&checked, 4096)) {
             return exit_with_help(settings, 1);
@@ -215,6 +224,16 @@
         settings->count_chars = true;
         settings->regex->count_chars = true;
     }
+    /* d */
+    if ((argflags & 8192) > 0) {
+      if (registerArgument(&checked, 8192)) {
+        return exit_with_help(settings, 1);
+      }
+      /* ignored together with -V */
+      if ((checked & 128) == 0) {
+        settings->dirsOnly = true;
+      }
+    }
     if (argflags == 0) {
       /* SHORTCUTS */
       if (strcmp(argv[t], "--exclude-cstyle-comments") == 0) {
@@ -247,33 +266,25 @@
     
     unsigned total = 0;
     if (directories->count == 0) {
-        add_string(directories, ".");
+        add_string(directories, "./");
     }
     for (unsigned t = 0 ; t < directories->count ; t++) {
       scanDirectory((scanner_t){directories->items[t], 0}, settings,
           output, result);
       total += result->result;
-      if (directories->count > 1 ) {
-        outbuf = (char*) malloc(81);
-        memset(outbuf, '-', 79);
-        outbuf[79] = '\n';
-        outbuf[80] = 0;
-        add_string(output, outbuf);
+      if (directories->count > 1) {
+        add_string(output, strdup(sepline_single));
         outbuf = (char*) malloc(81);
         snprintf(outbuf, 81, "%-63s%10u %s\n", directories->items[t],
                 result->result, result_type);
         add_string(output, outbuf);
-        outbuf = (char*) malloc(81);
-        memset(outbuf, '-', 79);
-        outbuf[79] = '\n';
-        outbuf[80] = 0;
-        add_string(output, outbuf);
+        add_string(output, strdup(sepline_single));
       }
     }
     destroy_string_list_t(directories);
 
     /* Print result */
-    if (settings->verbose) {
+    if (output != NULL) {
       for (int i = 0 ; i < output->count ; i++) {
         printf("%s", output->items[i]);
         free(output->items[i]);
@@ -281,9 +292,7 @@
       
       if (result->ext) {
         if (result->ext->count > 0) {
-          for (unsigned t = 0 ; t < 79 ; t++) {
-            printf("=");
-          }
+          fwrite(sepline_double, 1, 80, stdout);
           printf("\nIndividual sums:\n");
           for (unsigned t = 0 ; t < result->ext->count ; t++) {
             printf(" %-62s%10u %s\n",
@@ -293,11 +302,14 @@
           }
         }
       }
-      
-      for (unsigned t = 0 ; t < 79 ; t++) {
-        printf("=");
+
+      if (output->count > 0) {
+        fwrite(sepline_double, 1, 80, stdout);
+        printf("%73d %s\n", total, result_type);
+      } else {
+        /* If we only need to output a total, output it differently */
+        printf("%d %s\n", total, result_type);
       }
-      printf("\n%73d %s\n", total, result_type);
 
       if (settings->confusing_lnlen &&
           settings->regex->pattern_list->count > 0) {
--- a/src/cline.h	Sun Nov 10 14:06:03 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 
- * Copyright 2018 Mike Becker. All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CLINE_H_
-#define CLINE_H_
-
-#ifndef VERSION
-#error "VERSION macro must be set by build system"
-#endif
-
-#include "stdinc.h"
-#include "settings.h"
-
-#ifdef _cplusplus
-extern "C" {
-#endif
-
-void printHelpText();
-int exit_with_version(settings_t*);
-int exit_with_help(settings_t*, int);
-
-#ifdef _cplusplus
-}
-#endif
-
-#endif /* CLINE_H_ */
--- a/src/scanner.c	Sun Nov 10 14:06:03 2024 +0100
+++ b/src/scanner.c	Mon Apr 07 20:43:52 2025 +0200
@@ -199,27 +199,29 @@
 
     /* Scan subdirectories */
     if (!S_ISREG(filelist->st_mode)) {
-      if (settings->recursive && S_ISDIR(filelist->st_mode)) {
-        string_list_t *recoutput = new_string_list_t();
-        scanresult_t recresult;
-        recresult.ext = result->ext;
-        scanDirectory(
-            (scanner_t) {filelist->filename, scanner.spaces+1},
-            settings, recoutput, &recresult);
-        result->result += recresult.result;
-        if (!settings->matchesOnly || recoutput->count > 0) {
-          outbuf = (char*) malloc(81);
-          snprintf(outbuf, 81, "%*s/%*s%13u %s\n",
-              filelist->displayname_len+scanner.spaces, filelist->displayname,
-              60-filelist->displayname_len-scanner.spaces-1, "",
-              recresult.result, result_type);
-          add_string(output, outbuf);
-          for (unsigned i = 0 ; i < recoutput->count ; i++) {
-            add_string(output, recoutput->items[i]);
+      if (S_ISDIR(filelist->st_mode)) {
+        if (settings->recursive) {
+          string_list_t *recoutput = new_string_list_t();
+          scanresult_t recresult;
+          recresult.ext = result->ext;
+          scanDirectory(
+              (scanner_t) {filelist->filename, scanner.spaces+1},
+              settings, recoutput, &recresult);
+          result->result += recresult.result;
+          if (!settings->matchesOnly || recresult.result > 0) {
+            outbuf = (char*) malloc(81);
+            snprintf(outbuf, 81, "%*s/%*s%13u %s\n",
+                filelist->displayname_len+scanner.spaces, filelist->displayname,
+                60-filelist->displayname_len-scanner.spaces-1, "",
+                recresult.result, result_type);
+            add_string(output, outbuf);
+            for (unsigned i = 0 ; i < recoutput->count ; i++) {
+              add_string(output, recoutput->items[i]);
+            }
           }
+          destroy_string_list_t(recoutput);
         }
-        destroy_string_list_t(recoutput);
-      } else {
+      } else if (!settings->matchesOnly) {
         outbuf = (char*) malloc(81);
         snprintf(outbuf, 81, "%*s\n",
                  filelist->displayname_len+scanner.spaces,
@@ -288,7 +290,7 @@
 
           /* Print and sum line count */
           if (bfile) {
-            if (!settings->matchesOnly) {
+            if (!settings->matchesOnly && !settings->dirsOnly) {
               outbuf = (char*) malloc(81);
               snprintf(outbuf, 81,
                   "%*s%*s%19s\n", filelist->displayname_len+scanner.spaces,
@@ -299,20 +301,22 @@
           } else {
             addResultPerExtension(result->ext, filelist->ext, res_value);
             result->result += res_value;
-            outbuf = (char*) malloc(81);
-            snprintf(outbuf, 81, "%*s%*s%13u %s\n",
-                     filelist->displayname_len+scanner.spaces,
-                     filelist->displayname,
-                     60-filelist->displayname_len-scanner.spaces,
-                     "",
-                     res_value,
-                     result_type
-            );
-            add_string(output, outbuf);
+            if (!settings->dirsOnly) {
+              outbuf = (char*) malloc(81);
+              snprintf(outbuf, 81, "%*s%*s%13u %s\n",
+                       filelist->displayname_len+scanner.spaces,
+                       filelist->displayname,
+                       60-filelist->displayname_len-scanner.spaces,
+                       "",
+                       res_value,
+                       result_type
+              );
+              add_string(output, outbuf);
+            }
           }
         }
       } else {
-        if (!settings->matchesOnly) {
+        if (!settings->matchesOnly && !settings->dirsOnly) {
           /* Print hint */
           outbuf = (char*) malloc(81);
           snprintf(outbuf, 81, "%*s%*s%19s\n",
--- a/src/settings.c	Sun Nov 10 14:06:03 2024 +0100
+++ b/src/settings.c	Mon Apr 07 20:43:52 2025 +0200
@@ -44,6 +44,7 @@
     settings->regex              = new_regex_parser_t();
     settings->individual_sums    = false;
     settings->count_chars        = false;
+    settings->dirsOnly          = false;
   }
 
   return settings;
--- a/src/settings.h	Sun Nov 10 14:06:03 2024 +0100
+++ b/src/settings.h	Mon Apr 07 20:43:52 2025 +0200
@@ -44,6 +44,7 @@
   bool confusing_lnlen; /* this flag is set by the scanner */
   bool individual_sums;
   bool count_chars;
+  bool dirsOnly;
 } settings_t;
 
 #ifdef _cplusplus
--- a/src/stdinc.h	Sun Nov 10 14:06:03 2024 +0100
+++ b/src/stdinc.h	Mon Apr 07 20:43:52 2025 +0200
@@ -32,6 +32,7 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <dirent.h>
+#include <assert.h>
 #ifdef _MSC_VER
 #define strcasecmp _stricmp
 #if __STDC_VERSION__ < 202300L
--- a/vs/cline.vcxproj	Sun Nov 10 14:06:03 2024 +0100
+++ b/vs/cline.vcxproj	Mon Apr 07 20:43:52 2025 +0200
@@ -22,7 +22,6 @@
   <ItemGroup>
     <ClInclude Include="..\src\arguments.h" />
     <ClInclude Include="..\src\bfile_heuristics.h" />
-    <ClInclude Include="..\src\cline.h" />
     <ClInclude Include="..\src\regex_parser.h" />
     <ClInclude Include="..\src\scanner.h" />
     <ClInclude Include="..\src\settings.h" />
--- a/vs/cline.vcxproj.filters	Sun Nov 10 14:06:03 2024 +0100
+++ b/vs/cline.vcxproj.filters	Mon Apr 07 20:43:52 2025 +0200
@@ -40,9 +40,6 @@
     <ClInclude Include="..\src\bfile_heuristics.h">
       <Filter>Header</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\cline.h">
-      <Filter>Header</Filter>
-    </ClInclude>
     <ClInclude Include="..\src\regex_parser.h">
       <Filter>Header</Filter>
     </ClInclude>

mercurial