New function SB-EXT:ASSERT-VERSION->=
authorPaul Khuong <pvk@pvk.ca>
Thu, 14 Nov 2013 21:51:18 +0000 (16:51 -0500)
committerPaul Khuong <pvk@pvk.ca>
Thu, 14 Nov 2013 22:32:02 +0000 (17:32 -0500)
Executing (sb-ext:assert-version->= 1 1 13) signals a continuable
error if the running SBCL is older than 1.1.13 (and an undefined
function error before that).

Based on a patch by Philip Munksgaard.

Closes lp#674372.

NEWS
doc/manual/beyond-ansi.texinfo
package-data-list.lisp-expr
src/code/late-extensions.lisp
tests/interface.pure.lisp

diff --git a/NEWS b/NEWS
index ff74987..c9f52c7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,10 @@ changes relative to sbcl-1.1.13:
     include error messages instead of error codes.
   * enhancement: run-sbcl.sh is usefully handled by rlwrap.  Thanks to William
     Cushing. (lp#1249183)
+  * enhancement: new function SB-EXT:ASSERT-VERSION->= accepts a version
+    specification (multiple integer arguments) and signals a continuable error
+    if the current SBCL version is lower (older) than the specification.
+    (lp#674372)
   * bug fix: EQUALP now compares correctly structures with raw slots larger
     than a single word.
   * bug fix: contribs couldn't be built on Windows with MinGW.
index 75b1433..9825343 100644 (file)
@@ -795,6 +795,7 @@ different type of generator.
 @include fun-sb-ext-delete-directory.texinfo
 @include fun-sb-ext-get-time-of-day.texinfo
 @include macro-sb-ext-wait-for.texinfo
+@include fun-sb-ext-version-assert.texinfo
 
 @node Stale Extensions
 @comment  node-name,  next,  previous,  up
index 94fe875..ca67d02 100644 (file)
@@ -871,7 +871,10 @@ like *STACK-TOP-HINT* and unsupported stuff like *TRACED-FUN-LIST*."
                #!+sb-simd-pack "%SIMD-PACK-UB32S"
                #!+sb-simd-pack "%SIMD-PACK-UB64S"
                #!+sb-simd-pack "%SIMD-PACK-DOUBLES"
-               #!+sb-simd-pack "%SIMD-PACK-SINGLES"))
+               #!+sb-simd-pack "%SIMD-PACK-SINGLES"
+
+               ;; versioning utility
+               "ASSERT-VERSION->="))
 
    #s(sb-cold:package-data
       :name "SB!FORMAT"
index 48ee190..bcfaafe 100644 (file)
@@ -436,3 +436,51 @@ Works on all CASable places."
              for ,new = (cdr ,old)
              until (eq ,old (setf ,old ,cas-form))
              finally (return (car ,old))))))
+
+(defun split-version-string (string)
+  (loop
+    with start = 0
+    and end = (length string)
+    while (and start (< start end))
+    for subversion = (multiple-value-bind (subversion next)
+                         (parse-integer string :start start
+                                               :junk-allowed t)
+                       (setf start
+                             (and subversion
+                                  next
+                                  (< next end)
+                                  (eql #\. (aref string next))
+                                  (1+ next)))
+                       subversion)
+    when subversion
+      collect subversion))
+
+(defun version>= (x y)
+  (unless (or x y)
+    (return-from version>= t))
+  (let ((head-x (or (first x) 0))
+        (head-y (or (first y) 0)))
+    (or (> head-x head-y)
+        (and (= head-x head-y)
+             (version>= (rest x) (rest y))))))
+
+(defun assert-version->= (&rest subversions)
+  #!+sb-doc
+  "Asserts that the current SBCL is of version equal to or greater than
+the version specified in the arguments.  A continuable error is signaled
+otherwise.
+
+The arguments specify a sequence of subversion numbers in big endian order.
+They are compared lexicographically with the runtime version, and versions
+are treated as though trailed by an unbounded number of 0s.
+
+For example, (assert-version->= 1 1 4) asserts that the current SBCL is
+version 1.1.4[.0.0...] or greater, and (assert-version->= 1) that it is
+version 1[.0.0...] or greater."
+  (let ((version (split-version-string (lisp-implementation-version))))
+    (unless (version>= version subversions)
+      (cerror "Disregard this version requirement."
+              "SBCL ~A is too old for this program (version ~{~A~^.~} ~
+               or later is required)."
+              (lisp-implementation-version)
+              subversions))))
index 7e43f97..824c25e 100644 (file)
     (funcall fun1 1/7)
     (funcall fun1 1/100000000000000000000000000)
     (assert (< (- (get-universal-time) start-time) 2))))
+
+(with-test (:name :version-assert-ok)
+  (sb-ext:assert-version->= 1 1 13))
+
+(with-test (:name :version-assert-fails)
+  (assert (raises-error?
+           (sb-ext:assert-version->= most-positive-fixnum))))