home: hub: zuo

Download patch

ref: 23bf90a915a0065fe463b2365fea84c273e4ad49
parent: bdad684695b0b1b3078fdd488962044a631c2c22
author: Matthew Flatt <mflatt@racket-lang.org>
date: Tue Oct 17 02:32:33 CDT 2023

Zuo: repair `MAKEFLAGS` handling

The previous implementation relied on behavior of GNU Make 4.0, which
will add a space to the beginning of `MAKEFLAGS` when it doesn't start
with flags. The more general `MAKEFLAGS` convention (e.g, POSIX)
doesn't guarantee that, and so better parsing is needed.

--- a/lib/zuo/dry-run.zuo
+++ b/lib/zuo/dry-run.zuo
@@ -9,18 +9,45 @@
     (when (and mode (not (eq? mode sym)))
       (error (~a "`MAKEFLAGS` specified both " mode " and " sym " modes")))
     sym)
+  (define (no-touch mode)
+    (when (eq? mode 'touch)
+      (error "`MAKEFLAGS` indicates touch mode, which is not supported"))
+    mode)
   (and a
-       (let ([s (cdr a)])
-         (let loop ([i 0] [mode #f])
-           (cond
-             [(or (= i (string-length s)) 
-                  (equal? (char " ") (string-ref s i)))
-              mode]
-             [(equal? (char "n") (string-ref s i))
-              (loop (+ i 1) (new-mode mode 'dry-run))]
-             [(equal? (char "q") (string-ref s i))
-              (loop (+ i 1) (new-mode mode 'question))]
-             [(equal? (char "t") (string-ref s i))
-              (error "`MAKEFLAGS` has `-t`, but trace mode is not supported")]
-             [else
-              (loop (+ i 1) mode)])))))
+       (let loop ([l (shell->strings (cdr a))])
+         (and (pair? l)
+              (or
+               ;; If the first argument has only letters, then we
+               ;; assume it represents single-letter flags:
+               (let ([s (car l)])
+                 (let loop ([i 0] [mode #f])
+                   (cond
+                     [(= i (string-length s))
+                      (no-touch mode)]
+                     [(equal? (char "n") (string-ref s i))
+                      (loop (+ i 1) (new-mode mode 'dry-run))]
+                     [(equal? (char "q") (string-ref s i))
+                      (loop (+ i 1) (new-mode mode 'question))]
+                     [(equal? (char "t") (string-ref s i))
+                      (loop (+ i 1) (new-mode mode 'touch))]
+                     [(and (or (string<? (substring s i (+ i 1)) "a")
+                               (string<? "z" (substring s i (+ i 1))))
+                           (or (string<? (substring s i (+ i 1)) "A")
+                               (string<? "Z" (substring s i (+ i 1)))))
+                      ;; doesn't look like single-letter flags
+                      #f]
+                     [else
+                      (loop (+ i 1) mode)])))
+               ;; Otherwise, look for "-n", "-t", and "-q"
+               (let loop ([l l] [mode #f])
+                 (cond
+                   [(null? l)
+                    (no-touch mode)]
+                   [(equal? "-n" (car l))
+                    (loop (cdr l) (new-mode mode 'dry-run))]
+                   [(equal? "-q" (car l))
+                    (loop (cdr l) (new-mode mode 'question))]
+                   [(equal? "-t" (car l))
+                    (loop (cdr l) (new-mode mode 'touch))]
+                   [else
+                    (loop (cdr l) mode)])))))))