src/cline.c

changeset 95
8a20001544c1
parent 94
9637e3efb8e7
child 97
7b0357fdb304
--- a/src/cline.c	Tue Jun 30 12:00:16 2026 +0200
+++ b/src/cline.c	Tue Jun 30 14:19:08 2026 +0200
@@ -94,6 +94,61 @@
   return code;
 }
 
+static void normalize_excluded_dirs(settings_t *settings) {
+  /* normalize all paths */
+  for (int i = 0 ; i < settings->excludeDirs->count ; i++) {
+    char *arg = strdup(settings->excludeDirs->items[i]);
+    if (strpbrk(arg, "/\\") == NULL) {
+      /* do not normalize names */
+      settings->excludeDirs->items[i] = arg;
+    } else {
+      size_t arglen = strlen(arg);
+      /* fix file separators */
+      char fs = settings->fileSeparator;
+      char badfs = settings->fileSeparator == '/' ? '\\' : '/';
+      for (size_t j = 0 ; j < arglen ; j++) {
+        if (arg[j] == badfs) {
+          arg[j] = fs;
+        }
+      }
+      /* make path absolute */
+      {
+        char *ap = make_path_absolute(arg);
+        free(arg);
+        arg = ap;
+        arglen = strlen(ap);
+      }
+      /* make path canonical */
+      char *canonical = malloc(arglen+1);
+      size_t canonicallen = 0;
+      for (size_t j = 0 ; j < arglen ; j++) {
+        canonical[canonicallen++] = arg[j];
+        if (arg[j] == fs) {
+          /* collapse consecutive separators */
+          while (arg[j+1] == fs) j++;
+        } else if (arg[j] == '.') {
+          if (arg[j+1] == fs) {
+            /* skip '.' segments */
+            canonicallen--;
+            j++;
+          } else if (arg[j+1] == '.' && arg[j+2] == fs) {
+            /* trace back '..' segment */
+            canonicallen -= 2;
+            while (canonical[canonicallen-1] != fs) canonicallen--;
+            j+=2;
+          }
+        }
+      }
+      canonical[canonicallen] = '\0';
+      settings->excludeDirs->items[i] = canonical;
+      free(arg);
+    }
+  }
+
+  /* tell the string list to free the items */
+  settings->excludeDirs->free_item = free;
+}
+
 static const char * sepline_double = "===============================================================================\n";
 static const char * sepline_single = "-------------------------------------------------------------------------------\n";
 
@@ -242,8 +297,6 @@
       if (!checkParamOpt(&paropt) || t >= argc) {
         return exit_with_help(settings, 1);
       }
-      // TODO: normalize argument before adding to dir list
-      //       this makes it more efficient to compare dir names later
       add_string(settings->excludeDirs, argv[t]);
     }
     if (argflags == 0) {
@@ -280,13 +333,16 @@
     return 1;
   }
 
+  /* Normalize paths for excluded directories */
+  normalize_excluded_dirs(settings);
+
   /* Scan directories */
   scanresult_t* result = new_scanresult_t(settings);
   const char* result_type = settings->count_chars ? "chars" : "lines";
   bool has_output = false;
   unsigned total = 0;
   if (directories->count == 0) {
-      add_string(directories, "./");
+      add_string(directories, ".");
   }
   for (unsigned t = 0 ; t < directories->count ; t++) {
     /* Don't waste memory when only the total sum is needed */

mercurial