tools: fix three crashes that triggered the escalation loop

ober

c05a6e57be424f764352b00d5fb0e366fa4bf20d

diff --git a/src/jcode/core/repomap.ss b/src/jcode/core/repomap.ss
index 630f502..9069a00 100644
--- a/src/jcode/core/repomap.ss
+++ b/src/jcode/core/repomap.ss
@@ -88,7 +88,10 @@
       (mkdir dir))))
 
 (def (file-mtime-safe p)
-  (try (file-modification-time p)
+  ;; file-modification-time returns a <time> object, not a number; take its
+  ;; epoch seconds so the >/>= cache-freshness comparisons get a real number
+  ;; (else: "Exception in >: #<time-utc ...> is not a real number").
+  (try (time-second (file-modification-time p))
        (catch (e) 0)))
 
 ;;; --- Discovery ---
diff --git a/src/jcode/tool/file.ss b/src/jcode/tool/file.ss
index 07f03a6..e0c3483 100644
--- a/src/jcode/tool/file.ss
+++ b/src/jcode/tool/file.ss
@@ -297,7 +297,14 @@
     (unless pattern (error 'grep "Missing required parameter: pattern"))
     (unless path    (error 'grep "Missing required parameter: path"))
     (log-debug logger "grep" `((pattern . ,pattern) (path . ,path)))
-    (let ((regex   (pregexp pattern))
+    (let ((match?  (try
+                     (let ((rx (pregexp pattern)))
+                       (lambda (line) (and (pregexp-match rx line) #t)))
+                     (catch (e)
+                       ;; Pattern isn't a valid regex (e.g. a literal code
+                       ;; search such as "(def (foo" with unbalanced parens);
+                       ;; fall back to a plain substring match.
+                       (lambda (line) (and (string-contains line pattern) #t)))))
           (files   (if (file-directory? path)
                      (let* ((combined (string-append (strip-trailing-slash path) "/" file-glob))
                             (ms (glob-expand combined))
@@ -307,13 +314,13 @@
           (results '()))
       (for-each
         (lambda (file)
-          (when (file-exists? file)
+          (when (and (file-exists? file) (not (file-directory? file)))
             (call-with-input-file file
               (lambda (port)
                 (let loop ((line-num 1))
                   (let ((line (get-line port)))
                     (unless (eof-object? line)
-                      (when (pregexp-match regex line)
+                      (when (match? line)
                         (set! results
                           (cons (format "~a:~a:~a" file line-num line)
                                 results)))