#!/bin/sh #| -*- scheme -*- exec racket -um "$0" "$@" |# #lang racket/base (require version/utils racket/file) (define (patches) ;; no grouping parens in regexps (let* ([parts# (length (regexp-split #rx"[.]" the-version))] [concat (lambda xs (apply bytes-append (map (lambda (x) (if (string? x) (string->bytes/utf-8 x) x)) xs)))] [commas "<1>, *<2>, *<3>, *<4>"] [periods "<1>.<2>.<3>.<4>"] [rc-patch (list (concat "\r\n *FILEVERSION "commas" *" "\r\n *PRODUCTVERSION "commas" *\r\n") (concat "\r\n *VALUE \"FileVersion\", *\""commas "(?:\\\\0)?\"") (concat "\r\n *VALUE \"ProductVersion\", *\""commas "(?:\\\\0)?\""))] [manifest-patch (list (concat "assemblyIdentity[ \r\n]+" "version=\""periods"\"[ \r\n]"))]) `([#t ; only verify that it has the right contents "src/racket/src/schvers.h" ,(concat "\n#define MZSCHEME_VERSION \"<1>.<2>" (if (parts# . >= . 3) ".<3>" "") (if (parts# . >= . 4) ".<4>" "") "\"\n") ,@(for/list ([x+n (in-list '([X 1] [Y 2] [Z 3] [W 4]))]) (format "\n#define MZSCHEME_VERSION_~a ~a\n" (car x+n) (if ((cadr x+n) . > . parts#) "0" (format "<~a>" (cadr x+n)))))] ["src/worksp/racket/racket.rc" ,@rc-patch] ["src/worksp/gracket/gracket.rc" ,@rc-patch] ["src/worksp/starters/start.rc" ,@rc-patch] ["src/worksp/racket/racket.manifest" ,@manifest-patch] ["src/worksp/gracket/gracket.manifest" ,@manifest-patch] ["src/worksp/mzcom/mzobj.rgs" ,(concat "MzCOM.MzObj."periods" = s 'MzObj Class'") ,(concat "CurVer = s 'MzCOM.MzObj."periods"'") ,(concat "ProgID = s 'MzCOM.MzObj."periods"'")] ["src/worksp/mzcom/mzcom.rc" ,@rc-patch #"\r\n *CTEXT +\"MzCOM v. <1>.<2>\",IDC_STATIC" #"\r\n *CTEXT +\"Racket v. <1>.<2>\",IDC_STATIC"]))) (define the-version #f) (define getv (let ([vlist #f]) (lambda (i) (unless vlist (set! vlist (map (compose string->bytes/utf-8 number->string) (version->list the-version)))) (list-ref vlist i)))) (define (replace-pattern pattern buf err) (let* ([rx (regexp-replace* #rx#"<[1234]>" pattern #"([0-9]+)")] [vs (map (lambda (m) (let* ([m (regexp-replace #rx#"^<(.+)>$" m #"\\1")] [m (string->number (bytes->string/utf-8 m))]) (sub1 m))) (regexp-match* #rx#"<[1234]>" pattern))] [m (regexp-match-positions rx buf)]) (cond [(not m) (err "pattern ~s not found" pattern)] [(regexp-match? rx buf (cdar m)) (err "pattern ~s matches more than once" pattern)] [else (let loop ([m (cdr m)] [i 0] [vs vs] [r '()]) (cond [(and (null? m) (null? vs)) (apply bytes-append (reverse (cons (subbytes buf i) r)))] [(or (null? m) (null? vs)) (error "internal error")] [else (loop (cdr m) (cdar m) (cdr vs) (list* (getv (car vs)) (subbytes buf i (caar m)) r))]))]))) (define (do-patch file . specs) (let* ([only-verify? (eq? file #t)] [file (if only-verify? (car specs) file)] [specs (if only-verify? (cdr specs) specs)] [_ (begin (printf " ~a..." file) (flush-output))] [contents (file->bytes file)] [buf contents] [err (lambda (fmt . args) (error 'versionpatch "~a, in ~s" (apply format fmt args) file))]) (for ([spec (in-list specs)]) (set! buf (replace-pattern spec buf err))) (if (equal? buf contents) (printf (if only-verify? " verified.\n" " no change.\n")) (begin (printf " modified.\n") (if only-verify? (error 'versionpatch "this file is expected to have a correct version") (with-output-to-file file (lambda () (write-bytes buf)) #:exists 'truncate)))))) (provide main) (define (main ver) (set! the-version ver) ;; (printf "Patching files for ~a...\n" ver) (for ([p (in-list (patches))]) (apply do-patch p)) (printf "Done.\n"))