(module version-misc mzscheme
  (require (lib "")
           (lib "")
           (prefix 67: (lib "" "srfi"))
           (prefix 1: (lib "" "srfi")))
  (provide version<= version>= version= version< version>)
  ;; The definitions of mz-version, string->version, and
  ;; version<= were adapted (copied and pasted) from PLaneT's
  ;; implementation in (planet/private/
  (define-struct mz-version (numbers) #f)
  ;; string->version : string -> mz-version | #f
  (define (string->version str)
      ;; Old style numbering (with three digits in front)
      [(regexp-match #rx"^([0-9][0-9][0-9])([.0-9]*)$" str)
       (lambda (ver)
         (let* ([major (string->number (list-ref ver 1))]
                 (map string->number
                      (rest (regexp-split "\\." (list-ref ver 2))))]
                [minor (if (>= (length after-major) 1)
                           (first after-major)
                [maintenances (drop after-major 1)])
           (make-mz-version (list*
                             (remainder (quotient major 100) 10)
                             (remainder (quotient major 10) 10)
                             (remainder major 10)
      ;; New style numbering
      [(regexp-match #rx"^([.0-9]*)$" str)
       (lambda (ver)
         (let* ([numbers (regexp-split "\\." (list-ref ver 1))])
           (make-mz-version (map string->number numbers))))]
      [else #f]))
  ;; drop: (listof X) number -> (listof X)
  ;; A more permissive version of drop that returns the empty list
  ;; if we try to take off too many elements.
  (define (drop a-list n)
    (1:drop a-list (min n (length a-list))))
  ;; version-cmp: mz-version mz-version -> (union -1 0 1)
  ;; Returns -1 if v1 < v2, 0 if v1 = v2, and 1 if v1 > v2.
  (define (version-cmp v1 v2)
    (67:list-compare 67:integer-compare
                     (mz-version-numbers v1)
                     (mz-version-numbers v2)))
  ;; version<= : string string -> boolean
  ;; determines if a is the version string of an earlier
  ;; mzscheme release than b
  ;; [n.b. this relies on a guarantee from Matthew that
  ;; mzscheme version x1.y1 is older than version x2.y2 iff
  ;;  x1<x2 or x1=x2 and y1<y2]
  (define (version<= a b)
    (let ([a (string->version a)]
          [b (string->version b)])
      (not (= (version-cmp a b)

  (define (version>= a b)
    (let ([a (string->version a)]
          [b (string->version b)])
      (not (= (version-cmp a b)

  (define (version= a b)
    (let ([a (string->version a)]
          [b (string->version b)])
      (= (version-cmp a b)

  (define (version< a b)
    (let ([a (string->version a)]
          [b (string->version b)])
      (= (version-cmp a b)

  (define (version> a b)
    (let ([a (string->version a)]
          [b (string->version b)])
      (= (version-cmp a b)