fortrangoingonforty/fortsh / 3d82656

Browse files

use glob pattern matching in expansion module pattern_replace and match_pattern — supports [charclass] and full glob syntax

Authored by espadonne
SHA
3d826564ca3b5030ed65b14b731e30d51c98a8f0
Parents
2fa4e73
Tree
a6b852c

2 changed files

StatusFile+-
M Makefile 1 1
M src/scripting/expansion.f90 11 53
Makefilemodified
@@ -303,7 +303,7 @@ $(BUILDDIR)/scripting/variables.o: src/scripting/variables.f90 $(BUILDDIR)/commo
303303
 $(BUILDDIR)/scripting/prompt_formatting.o: src/scripting/prompt_formatting.f90 $(BUILDDIR)/common/types.o $(BUILDDIR)/system/interface.o $(BUILDDIR)/scripting/substitution.o | $(BUILDDIR)/scripting
304304
 	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
305305
 
306
-$(BUILDDIR)/scripting/expansion.o: src/scripting/expansion.f90 $(BUILDDIR)/common/types.o $(BUILDDIR)/scripting/variables.o $(BUILDDIR)/execution/command_capture.o | $(BUILDDIR)/scripting
306
+$(BUILDDIR)/scripting/expansion.o: src/scripting/expansion.f90 $(BUILDDIR)/common/types.o $(BUILDDIR)/scripting/variables.o $(BUILDDIR)/execution/command_capture.o $(BUILDDIR)/parsing/glob.o | $(BUILDDIR)/scripting
307307
 	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
308308
 
309309
 $(BUILDDIR)/scripting/substitution.o: src/scripting/substitution.f90 $(BUILDDIR)/common/types.o $(BUILDDIR)/system/interface.o $(BUILDDIR)/execution/command_capture.o | $(BUILDDIR)/scripting
src/scripting/expansion.f90modified
@@ -6,6 +6,7 @@ module expansion
66
   use shell_types
77
   use variables  ! includes check_nounset
88
   use command_capture, only: execute_command_and_capture
9
+  use glob, only: pattern_matches_no_dotfile_check
910
   use iso_fortran_env, only: output_unit, error_unit
1011
 #ifdef USE_C_STRINGS
1112
   use iso_c_binding, only: c_char, c_int, c_null_char, c_ptr, c_f_pointer, c_size_t
@@ -1260,22 +1261,20 @@ contains
12601261
 
12611262
     i2 = 1
12621263
     do while (i2 <= in_len)
1264
+      ! Try glob pattern match at position i2 — find shortest match
12631265
       matched = .false.
1264
-      if (i2 + pat_len - 1 <= in_len) then
1265
-        matched = .true.
1266
-        do j2 = 1, pat_len
1267
-          if (input(i2+j2-1:i2+j2-1) /= pattern(j2:j2)) then
1268
-            matched = .false.
1269
-            exit
1270
-          end if
1271
-        end do
1272
-      end if
1266
+      do j2 = 1, in_len - i2 + 1
1267
+        if (pattern_matches_no_dotfile_check(pattern(1:pat_len), input(i2:i2+j2-1))) then
1268
+          matched = .true.
1269
+          exit  ! j2 = matched length
1270
+        end if
1271
+      end do
12731272
       if (matched) then
12741273
         if (repl_len > 0) then
12751274
           result_buf(out_pos:out_pos + repl_len - 1) = replacement(1:repl_len)
12761275
           out_pos = out_pos + repl_len
12771276
         end if
1278
-        i2 = i2 + pat_len
1277
+        i2 = i2 + j2  ! skip matched portion
12791278
         if (.not. replace_all) then
12801279
           do while (i2 <= in_len)
12811280
             result_buf(out_pos:out_pos) = input(i2:i2)
@@ -1427,52 +1426,11 @@ contains
14271426
   end subroutine
14281427
 
14291428
   ! Simple pattern matching (supports * and ? wildcards)
1429
+  ! Delegate to glob module's pattern matcher which handles *, ?, [...]
14301430
   function match_pattern(str, pattern) result(matches)
14311431
     character(len=*), intent(in) :: str, pattern
14321432
     logical :: matches
1433
-    integer :: s_pos, p_pos, s_len, p_len
1434
-    integer :: star_pos, s_star_pos
1435
-
1436
-    s_len = len_trim(str)
1437
-    p_len = len_trim(pattern)
1438
-    s_pos = 1
1439
-    p_pos = 1
1440
-    star_pos = 0
1441
-    s_star_pos = 0
1442
-
1443
-    do while (s_pos <= s_len)
1444
-      if (p_pos <= p_len) then
1445
-        if (pattern(p_pos:p_pos) == '*') then
1446
-          ! Found *, record position and try to match rest
1447
-          star_pos = p_pos
1448
-          s_star_pos = s_pos
1449
-          p_pos = p_pos + 1
1450
-          cycle
1451
-        else if (pattern(p_pos:p_pos) == '?' .or. pattern(p_pos:p_pos) == str(s_pos:s_pos)) then
1452
-          ! Match single character
1453
-          p_pos = p_pos + 1
1454
-          s_pos = s_pos + 1
1455
-          cycle
1456
-        end if
1457
-      end if
1458
-
1459
-      ! No match, backtrack if we had a *
1460
-      if (star_pos > 0) then
1461
-        p_pos = star_pos + 1
1462
-        s_star_pos = s_star_pos + 1
1463
-        s_pos = s_star_pos
1464
-      else
1465
-        matches = .false.
1466
-        return
1467
-      end if
1468
-    end do
1469
-
1470
-    ! Check remaining pattern for trailing *
1471
-    do while (p_pos <= p_len .and. pattern(p_pos:p_pos) == '*')
1472
-      p_pos = p_pos + 1
1473
-    end do
1474
-
1475
-    matches = (p_pos > p_len)
1433
+    matches = pattern_matches_no_dotfile_check(pattern, str)
14761434
   end function
14771435
 
14781436
   ! ============================================================================