@@ -6,6 +6,7 @@ module expansion |
| 6 | 6 | use shell_types |
| 7 | 7 | use variables ! includes check_nounset |
| 8 | 8 | use command_capture, only: execute_command_and_capture |
| 9 | + use glob, only: pattern_matches_no_dotfile_check |
| 9 | 10 | use iso_fortran_env, only: output_unit, error_unit |
| 10 | 11 | #ifdef USE_C_STRINGS |
| 11 | 12 | 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 |
| 1260 | 1261 | |
| 1261 | 1262 | i2 = 1 |
| 1262 | 1263 | do while (i2 <= in_len) |
| 1264 | + ! Try glob pattern match at position i2 — find shortest match |
| 1263 | 1265 | 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 |
| 1273 | 1272 | if (matched) then |
| 1274 | 1273 | if (repl_len > 0) then |
| 1275 | 1274 | result_buf(out_pos:out_pos + repl_len - 1) = replacement(1:repl_len) |
| 1276 | 1275 | out_pos = out_pos + repl_len |
| 1277 | 1276 | end if |
| 1278 | | - i2 = i2 + pat_len |
| 1277 | + i2 = i2 + j2 ! skip matched portion |
| 1279 | 1278 | if (.not. replace_all) then |
| 1280 | 1279 | do while (i2 <= in_len) |
| 1281 | 1280 | result_buf(out_pos:out_pos) = input(i2:i2) |
@@ -1427,52 +1426,11 @@ contains |
| 1427 | 1426 | end subroutine |
| 1428 | 1427 | |
| 1429 | 1428 | ! Simple pattern matching (supports * and ? wildcards) |
| 1429 | + ! Delegate to glob module's pattern matcher which handles *, ?, [...] |
| 1430 | 1430 | function match_pattern(str, pattern) result(matches) |
| 1431 | 1431 | character(len=*), intent(in) :: str, pattern |
| 1432 | 1432 | 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) |
| 1476 | 1434 | end function |
| 1477 | 1435 | |
| 1478 | 1436 | ! ============================================================================ |