diff --git a/babel-speed.asd b/babel-speed.asd
new file mode 100644
index 0000000..46ae0da
--- /dev/null
+++ b/babel-speed.asd
@@ -0,0 +1,44 @@
+;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
+;;;
+;;; babel-speed.asd --- ASDF system definition for Babel speed measurement.
+;;;
+;;; Copyright (C) 2007, Luis Oliveira  <loliveira@common-lisp.net>
+;;;
+;;; Permission is hereby granted, free of charge, to any person
+;;; obtaining a copy of this software and associated documentation
+;;; files (the "Software"), to deal in the Software without
+;;; restriction, including without limitation the rights to use, copy,
+;;; modify, merge, publish, distribute, sublicense, and/or sell copies
+;;; of the Software, and to permit persons to whom the Software is
+;;; furnished to do so, subject to the following conditions:
+;;;
+;;; The above copyright notice and this permission notice shall be
+;;; included in all copies or substantial portions of the Software.
+;;;
+;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;;; NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+;;; DEALINGS IN THE SOFTWARE.
+
+(defsystem babel-speed
+  :description "Speed measurement for Babel."
+  :depends-on (babel)
+  :components
+  ((:module "speed"
+    :serial t
+    :components
+    ((:file "speed")))))
+
+(defclass speed-op (asdf::operation) ())
+
+(defmethod perform ((o speed-op) (c (eql (find-system :babel-speed))))
+  (funcall (intern (string '#:run-speed) '#:babel-speed)))
+
+(defmethod operation-done-p ((o speed-op) (c (eql (find-system :babel-speed))))
+  nil)
+
+;;; vim: ft=lisp et
diff --git a/babel.asd b/babel.asd
index 6c1348f..aac7a8c 100644
--- a/babel.asd
+++ b/babel.asd
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+(in-package :asdf)
+
 (defsystem babel
   :description "Babel, a charset conversion library."
   :author "Luis Oliveira <loliveira@common-lisp.net>"
diff --git a/build.xcvb b/build.xcvb
new file mode 100644
index 0000000..04fe583
--- /dev/null
+++ b/build.xcvb
@@ -0,0 +1,20 @@
+#+xcvb
+(module
+ (:fullname "babel"
+  :depends-on ("src/packages"
+	       "src/encodings"
+	       "src/enc-ascii"
+	       "src/enc-ebcdic"
+	       "src/enc-iso-8859"
+	       "src/enc-unicode"
+               "src/enc-cp1251"
+               "src/enc-cp1252"
+               "src/jpn-table"
+               "src/enc-jpn"
+               "src/gbk-map"
+               "src/enc-gbk"
+	       "src/external-format"
+	       "src/strings"
+	       "src/sharp-backslash")
+  :build-depends-on ((:asdf "alexandria") (:asdf "trivial-features"))
+  :supersedes-asdf ("babel")))
diff --git a/speed/speed.lisp b/speed/speed.lisp
new file mode 100644
index 0000000..876ced6
--- /dev/null
+++ b/speed/speed.lisp
@@ -0,0 +1,88 @@
+;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
+;;;
+;;; speed.lisp --- Speed measurement for Babel.
+;;;
+;;; Copyright (C) 2007-2008, Luis Oliveira  <loliveira@common-lisp.net>
+;;;
+;;; Permission is hereby granted, free of charge, to any person
+;;; obtaining a copy of this software and associated documentation
+;;; files (the "Software"), to deal in the Software without
+;;; restriction, including without limitation the rights to use, copy,
+;;; modify, merge, publish, distribute, sublicense, and/or sell copies
+;;; of the Software, and to permit persons to whom the Software is
+;;; furnished to do so, subject to the following conditions:
+;;;
+;;; The above copyright notice and this permission notice shall be
+;;; included in all copies or substantial portions of the Software.
+;;;
+;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;;; NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+;;; DEALINGS IN THE SOFTWARE.
+
+(in-package #:cl-user)
+(defpackage #:babel-speed
+  (:use #:common-lisp #:babel #:babel-encodings))
+(in-package #:babel-speed)
+
+(defun run-speed ()
+  "This is the top-level function, called from the speed-op ASDF operation."
+  (format t "~&Speed measurement of decoding UTF8 by Babel.~%")
+  (format t "Decode the test file...")
+  (format t " Times: ~s~%" (decode-file))
+  (loop for length in '(0 2 5 10 50 100)
+        for repeats in '(10000000 10000000 10000000 10000000 5000000 1000000)
+        do (format t "Decode ~d bytes..." length)
+           (format t " Times: ~s~%" (decode-array length repeats))))
+
+(defun test-file (name type)
+  "Copied from test suite.  Get the pathname for the test file
+   designated by NAME and TYPE."
+  (let ((sys-pn (truename
+                 (asdf:system-definition-pathname
+                  (asdf:find-system 'babel-tests)))))
+    (make-pathname :name name :type type
+                   :directory (append (pathname-directory sys-pn)
+                                      '("tests"))
+                   :defaults sys-pn)))
+
+;;; Note: the test file contains 14052 octets
+(defun read-test-file (name type)
+  "Copied from test suite.  Read in the test file designated by NAME and TYPE.
+   Return the contents as an array of octets (unsigned bytes)."
+  (with-open-file (in (test-file name type) :element-type '(unsigned-byte 8))
+    (let* ((data (loop for byte = (read-byte in nil nil)
+                       until (null byte) collect byte)))
+      (make-array (length data) :element-type '(unsigned-byte 8)
+                  :initial-contents data))))
+
+(defun decode-octets (utf8-octets iter)
+  "UTF8-OCTETS is an array of octets.  Five times, decode the array ITER
+   times.  Return a list of five elements.  Each element is the number of
+   microseconds to decode the array.  It's done this way so that a
+   person can discard outliers."
+  (let ((times nil))
+    (dotimes (i 5)
+      (let ((start-time (quux:log-get-time)))
+        (dotimes (j iter)
+          (octets-to-string utf8-octets #|| :encoding :utf-8 ||#))
+        (let ((end-time (quux:log-get-time)))
+          (push (/ (float (- end-time start-time))
+                   (float iter))
+                times))))
+      times))
+
+(defun decode-file ()
+  "Return the 5-list characterizing the time it takes to decode the
+   contents of the test file."
+  (decode-octets (read-test-file "utf-32" "txt-utf8") 10000))
+
+(defun decode-array (length &optional (repeats 10000000))
+  "Return the 5-list characterizing the time it takes to decode a
+   byte array the given LENGTH."
+  (decode-octets (make-array length :element-type '(unsigned-byte 8) :initial-element 85)
+                 repeats))
diff --git a/src/enc-ascii.lisp b/src/enc-ascii.lisp
index dd26d13..eeec90f 100644
--- a/src/enc-ascii.lisp
+++ b/src/enc-ascii.lisp
@@ -24,8 +24,11 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/packages" "src/encodings")))
+
 (in-package #:babel-encodings)
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
 (define-character-encoding :ascii
     "A 7-bit, fixed-width character encoding in which all
 character codes map to their Unicode equivalents."
@@ -41,3 +44,4 @@ character codes map to their Unicode equivalents."
   (if (>= octet 128)
       (handle-error)
       octet))
+) ;; end EVAL-WHEN
diff --git a/src/enc-cp1251.lisp b/src/enc-cp1251.lisp
index 8bcead0..621db78 100644
--- a/src/enc-cp1251.lisp
+++ b/src/enc-cp1251.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/encodings")))
+
 (in-package #:babel-encodings)
 
 (define-character-encoding :cp1251
diff --git a/src/enc-cp1252.lisp b/src/enc-cp1252.lisp
index cae80d8..7572323 100644
--- a/src/enc-cp1252.lisp
+++ b/src/enc-cp1252.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/encodings")))
+
 (in-package #:babel-encodings)
 
 (define-character-encoding :cp1252
diff --git a/src/enc-ebcdic.lisp b/src/enc-ebcdic.lisp
index 6977da4..dfe210e 100644
--- a/src/enc-ebcdic.lisp
+++ b/src/enc-ebcdic.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/packages" "src/encodings")))
+
 (in-package #:babel-encodings)
 
 (define-character-encoding :ebcdic-us
@@ -56,8 +58,9 @@
 
 (define-constant +ebcdic-encode-table+
   (loop with rt = (make-array 256 :element-type 'ub8 :initial-element 0)
-        for code across +ebcdic-decode-table+ for i from 0 do
-        (assert (= 0 (aref rt code)))
+        for code fixnum across +ebcdic-decode-table+
+        for i fixnum from 0 do
+        (assert (= 0 (the fixnum (aref rt code))))
         (setf (aref rt code) i)
         finally (return rt))
   :test #'equalp)
diff --git a/src/enc-gbk.lisp b/src/enc-gbk.lisp
index e95d062..ffa5c1f 100644
--- a/src/enc-gbk.lisp
+++ b/src/enc-gbk.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/encodings")))
+
 (in-package #:babel-encodings)
 
 ;; populated in gbk-map.lisp
diff --git a/src/enc-iso-8859.lisp b/src/enc-iso-8859.lisp
index aeed673..5f23878 100644
--- a/src/enc-iso-8859.lisp
+++ b/src/enc-iso-8859.lisp
@@ -27,6 +27,8 @@
 ;;; This implementation is largely based on OpenMCL's l1-unicode.lisp
 ;;;   Copyright (C) 2006 Clozure Associates and contributors.
 
+#+xcvb (module (:depends-on ("src/packages" "src/encodings")))
+
 (in-package #:babel-encodings)
 
 ;;; Typically, ISO-8859-* codes in the range #x00-#x9f map straight
diff --git a/src/enc-jpn.lisp b/src/enc-jpn.lisp
index e5ecace..0e30d83 100644
--- a/src/enc-jpn.lisp
+++ b/src/enc-jpn.lisp
@@ -3,6 +3,8 @@
 ;;; enc-jpn.lisp --- Japanese encodings.
 ;;;
 
+#+xcvb (module (:depends-on ("src/jpn-table" "src/encodings")))
+
 (in-package #:babel-encodings)
 
 ;;;; helper functions
diff --git a/src/enc-unicode.lisp b/src/enc-unicode.lisp
index a23f430..7a057db 100644
--- a/src/enc-unicode.lisp
+++ b/src/enc-unicode.lisp
@@ -27,6 +27,8 @@
 ;;; This implementation is largely based on OpenMCL's l1-unicode.lisp
 ;;;   Copyright (C) 2006 Clozure Associates and contributors.
 
+#+xcvb (module (:depends-on ("src/packages" "src/encodings")))
+
 (in-package #:babel-encodings)
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
@@ -35,14 +37,63 @@
   (defconstant +swapped-byte-order-mark-code+ #xfffe)
   (defconstant +swapped-byte-order-mark-code-32+ #xfffe0000))
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (assert (<= #x10ffff most-positive-fixnum) ()
+          "MOST-POSITIVE-FIXNUM too small for a fixnum to hold an arbitrary unicode codepoint"))
+
 ;;; Some convenience macros adding FIXNUM declarations.
-(defmacro f-ash (integer count) `(the fixnum (ash ,integer ,count)))
-(defmacro f-logior (&rest integers) `(the fixnum (logior ,@integers)))
-(defmacro f-logand (&rest integers) `(the fixnum (logand ,@integers)))
-(defmacro f-logxor (&rest integers) `(the fixnum (logxor ,@integers)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defmacro f-+ (&rest fixnums)
+  "A version of the + function that can only be used on fixnums."
+  `(the fixnum (+ ,@(loop for n in fixnums collect `(the fixnum ,n)))))
+
+(defmacro f-- (number &rest fixnums)
+  "A version of the - function that can only be used on fixnums."
+  `(the fixnum (- (the fixnum ,number) ,@(loop for n in fixnums collect `(the fixnum ,n)))))
+
+(defmacro f-1+ (n)
+  "A version of the 1+ function that can only be used on fixnums."
+  `(the fixnum (+ (the fixnum ,n) 1)))
+
+(defmacro f-ash    (integer count)
+  "A version of the ash function that can only be used on fixnums."
+  `(the fixnum (ash (the fixnum ,integer) (the fixnum ,count))))
+
+(defmacro f-logior (&rest fixnums)
+  "A version of the logior function that can only be used on fixnums."
+  (if (cdr fixnums)
+    `(the fixnum (logior (the fixnum ,(car fixnums))
+			 ,(if (cddr fixnums)
+                            `(f-logior ,@(cdr fixnums))
+                            `(the fixnum ,(cadr fixnums)))))
+    `(the fixnum ,(car fixnums))))
+
+(defmacro f-logand (&rest fixnums)
+  "A version of the logand function that can only be used on fixnums."
+  (if (cdr fixnums)
+    `(the fixnum (logand (the fixnum ,(car fixnums))
+			 ,(if (cddr fixnums)
+                            `(f-logand ,@(cdr fixnums))
+                            `(the fixnum ,(cadr fixnums)))))
+    `(the fixnum ,(car fixnums))))
+
+(defmacro f-logxor (&rest fixnums)
+  "A version of the logxor function that can only be used on fixnums."
+  (if (cdr fixnums)
+    `(the fixnum (logxor (the fixnum ,(car fixnums))
+			 ,(if (cddr fixnums)
+                            `(f-logxor ,@(cdr fixnums))
+                            `(the fixnum ,(cadr fixnums)))))
+    `(the fixnum ,(car fixnums))))
+
+(defmacro f-incf (place &optional (delta 1))
+  `(the fixnum (setf ,place (the fixnum (+ (the fixnum ,place) (the fixnum ,delta)))))))
+
 
 ;;;; UTF-8
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
 (define-character-encoding :utf-8
     "An 8-bit, variable-length character encoding in which
 character code points in the range #x00-#x7f can be encoded in a
@@ -52,6 +103,7 @@ in 2 to 4 bytes."
   :literal-char-code-limit #x80
   :bom-encoding #(#xef #xbb #xbf)
   :default-replacement #xfffd)
+) ;; end EVAL-WHEN
 
 (define-condition invalid-utf8-starter-byte (character-decoding-error)
   ()
@@ -72,11 +124,11 @@ in 2 to 4 bytes."
      (loop with noctets fixnum = 0
            for i fixnum from start below end
            for code of-type code-point = (,getter seq i) do
-           (let ((new (+ (cond ((< code #x80) 1)
-                               ((< code #x800) 2)
-                               ((< code #x10000) 3)
-                               (t 4))
-                         noctets)))
+           (let ((new (f-+ (cond ((< code #x80) 1)
+                                 ((< code #x800) 2)
+                                 ((< code #x10000) 3)
+                                 (t 4))
+                           noctets)))
              (if (and (plusp max) (> new max))
                  (loop-finish)
                  (setq noctets new)))
@@ -90,17 +142,17 @@ in 2 to 4 bytes."
            while (< i end) do
            ;; check for invalid continuation bytes
            (macrolet ((invalid-cb-p (n)
-                        `(and (< (+ i ,n) end)
-                              (not (< #x7f (,',getter seq (+ i ,n)) #xc0)))))
+                        `(and (< (f-+ i ,n) end)
+                              (not (< #x7f (,',getter seq (f-+ i ,n)) #xc0)))))
              ;; wrote this code with LET instead of FOR because CLISP's
              ;; LOOP doesn't like WHILE clauses before FOR clauses.
              (let* ((octet (,getter seq i))
-                    (next-i (+ i (cond ((or (< octet #xc0) (invalid-cb-p 1)) 1)
-                                       ((or (< octet #xe0) (invalid-cb-p 2)) 2)
-                                       ((or (< octet #xf0) (invalid-cb-p 3)) 3)
-                                       ((or (< octet #xf8) (invalid-cb-p 4)) 4)
-                                       ((or (< octet #xfc) (invalid-cb-p 5)) 5)
-                                       (t 6)))))
+                    (next-i (f-+ i (cond ((or (< octet #xc0) (invalid-cb-p 1)) 1)
+                                         ((or (< octet #xe0) (invalid-cb-p 2)) 2)
+                                         ((or (< octet #xf0) (invalid-cb-p 3)) 3)
+                                         ((or (< octet #xf8) (invalid-cb-p 4)) 4)
+                                         ((or (< octet #xfc) (invalid-cb-p 5)) 5)
+                                         (t 6)))))
                (declare (type ub8 octet) (fixnum next-i))
                (cond
                  ((> next-i end)
@@ -117,9 +169,9 @@ in 2 to 4 bytes."
                   ;; FIXME: The data for this error is not right.
                   (decoding-error (vector octet) :utf-8 seq i
                                   nil 'end-of-input-in-character)
-                  (return (values (1+ nchars) end)))
+                  (return (values (f-1+ nchars) end)))
                  (t
-                  (setq nchars (1+ nchars)
+                  (setq nchars (f-1+ nchars)
                         i next-i)
                   (when (and (plusp max) (= nchars max))
                     (return (values nchars i)))))))
@@ -127,6 +179,7 @@ in 2 to 4 bytes."
                      (assert (= i end))
                      (return (values nchars i))))))
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
 (define-encoder :utf-8 (getter src-type setter dest-type)
   `(named-lambda utf-8-encoder (src start end dest d-start)
      (declare (type ,src-type src)
@@ -136,31 +189,32 @@ in 2 to 4 bytes."
            for i fixnum from start below end
            for code of-type code-point = (,getter src i) do
            (macrolet ((set-octet (offset value)
-                        `(,',setter ,value dest (the fixnum (+ di ,offset)))))
+                        `(,',setter ,value dest (f-+ di ,offset))))
              (cond
                ;; 1 octet
                ((< code #x80)
                 (set-octet 0 code)
-                (incf di))
+                (f-incf di))
                ;; 2 octets
                ((< code #x800)
-                (set-octet 0 (logior #xc0 (f-ash code -6)))
-                (set-octet 1 (logior #x80 (f-logand code #x3f)))
-                (incf di 2))
+                (set-octet 0 (f-logior #xc0 (f-ash code -6)))
+                (set-octet 1 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 2))
                ;; 3 octets
                ((< code #x10000)
-                (set-octet 0 (logior #xe0 (f-ash code -12)))
-                (set-octet 1 (logior #x80 (f-logand #x3f (f-ash code -6))))
-                (set-octet 2 (logior #x80 (f-logand code #x3f)))
-                (incf di 3))
+                (set-octet 0 (f-logior #xe0 (f-ash code -12)))
+                (set-octet 1 (f-logior #x80 (f-logand #x3f (f-ash code -6))))
+                (set-octet 2 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 3))
                ;; 4 octets
                (t
-                (set-octet 0 (logior #xf0 (f-logand #x07 (f-ash code -18))))
-                (set-octet 1 (logior #x80 (f-logand #x3f (f-ash code -12))))
-                (set-octet 2 (logior #x80 (f-logand #x3f (f-ash code -6))))
-                (set-octet 3 (logior #x80 (logand code #x3f)))
-                (incf di 4))))
-           finally (return (the fixnum (- di d-start))))))
+                (set-octet 0 (f-logior #xf0 (f-logand #x07 (f-ash code -18))))
+                (set-octet 1 (f-logior #x80 (f-logand #x3f (f-ash code -12))))
+                (set-octet 2 (f-logior #x80 (f-logand #x3f (f-ash code -6))))
+                (set-octet 3 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 4))))
+           finally (return (f-- di d-start)))))
+) ;; end EVAL-WHEN
 
 (define-decoder :utf-8 (getter src-type setter dest-type)
   `(named-lambda utf-8-decoder (src start end dest d-start)
@@ -178,7 +232,8 @@ in 2 to 4 bytes."
              ;; checks this.
              (macrolet
                  ((consume-octet ()
-                    `(let ((next-i (incf i)))
+                    `(let ((next-i (f-incf i)))
+                       (declare (fixnum next-i))
                        (if (= next-i end)
                            ;; FIXME: data for this error is incomplete.
                            ;; and signalling this error twice
@@ -208,8 +263,8 @@ in 2 to 4 bytes."
                        ((< u1 #xc2)
                         (handle-error 2 overlong-utf8-sequence))
                        ((< u1 #xe0)     ; 2 octets
-                        (logior (f-ash (f-logand #x1f u1) 6)
-                                (f-logxor u2 #x80)))
+                        (f-logior (f-ash (f-logand #x1f u1) 6)
+                                  (f-logxor u2 #x80)))
                        (t
                         (setq u3 (consume-octet))
                         (handle-error-if-icb u3 2)
@@ -256,7 +311,7 @@ in 2 to 4 bytes."
                                     (handle-error 6 character-out-of-range)
                                     )))))))))))))
                 dest di))
-             finally (return (the fixnum (- di d-start)))))))
+             finally (return (f-- di d-start))))))
 
 ;;;; UTF-8B
 
@@ -323,12 +378,12 @@ code points for each invalid byte."
      (loop with noctets fixnum = 0
            for i fixnum from start below end
            for code of-type code-point = (,getter seq i) do
-           (let ((new (+ (cond ((< code #x80) 1)
-                               ((< code #x800) 2)
-                               ((<= #xdc80 code #xdcff) 1)
-                               ((< code #x10000) 3)
-                               (t 4))
-                         noctets)))
+           (let ((new (f-+ (cond ((< code #x80) 1)
+                                 ((< code #x800) 2)
+                                 ((<= #xdc80 code #xdcff) 1)
+                                 ((< code #x10000) 3)
+                                 (t 4))
+                           noctets)))
              (if (and (plusp max) (> new max))
                  (loop-finish)
                  (setq noctets new)))
@@ -349,22 +404,22 @@ code points for each invalid byte."
                                  (t 4))))
              (declare (type ub8 octet) (fixnum noctets))
              (cond
-               ((> (+ i noctets) end)
+               ((> (f-+ i noctets) end)
                 ;; If this error is suppressed these last few bytes
                 ;; will be encoded as raw bytes later.
                 (decoding-error (vector octet) :utf-8 seq i
                                 nil 'end-of-input-in-character)
-                (return (values (+ nchars (- end i)) end)))
+                (return (values (f-+ nchars (- end i)) end)))
                (t
                 ;; FIXME: clean this mess up.
                 (let* ((u1 octet)
-                       (u2 (if (>= noctets 2) (,getter seq (1+ i)) 0))
-                       (u3 (if (>= noctets 3) (,getter seq (+ i 2)) 0))
-                       (u4 (if (= noctets 4) (,getter seq (+ i 3)) 0))
+                       (u2 (if (>= noctets 2) (,getter seq (f-1+ i)) 0))
+                       (u3 (if (>= noctets 3) (,getter seq (f-+ i 2)) 0))
+                       (u4 (if (= noctets 4) (,getter seq (f-+ i 3)) 0))
                        (inc (or (and (> noctets 1)
                                      (< u1 #xc2))
                                 (and (= noctets 2)
-                                     (not (logior u2 #x40)))
+                                     (not (f-logior u2 #x40)))
                                 (and (= noctets 3)
                                      (not (and (< (f-logxor u2 #x80) #x40)
                                                (< (f-logxor u3 #x80) #x40)
@@ -376,10 +431,11 @@ code points for each invalid byte."
                                            (< (f-logxor u3 #x80) #x40)
                                            (< (f-logxor u4 #x80) #x40)
                                            (or (>= u1 #xf1) (>= u2 #x90))))))))
-                  (let ((new-nchars (if inc (+ nchars noctets) (1+ nchars))))
+                  (let ((new-nchars (if inc (f-+ nchars noctets) (f-1+ nchars))))
+                    (declare (fixnum new-nchars))
                     (when (and (plusp max) (> new-nchars max))
                       (return (values nchars i)))
-                    (incf i noctets)
+                    (f-incf i noctets)
                     (setq nchars new-nchars))))))
            finally (progn
                      (assert (= i end))
@@ -395,35 +451,35 @@ code points for each invalid byte."
            for i fixnum from start below end
            for code of-type code-point = (,getter src i) do
            (macrolet ((set-octet (offset value)
-                        `(,',setter ,value dest (the fixnum (+ di ,offset)))))
+                        `(,',setter ,value dest (f-+ di ,offset))))
              (cond
                ;; 1 octet
                ((< code #x80)
                 (set-octet 0 code)
-                (incf di))
+                (f-incf di))
                ;; 2 octets
                ((< code #x800)
-                (set-octet 0 (logior #xc0 (f-ash code -6)))
-                (set-octet 1 (logior #x80 (f-logand code #x3f)))
-                (incf di 2))
+                (set-octet 0 (f-logior #xc0 (f-ash code -6)))
+                (set-octet 1 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 2))
                ;; 1 octet (invalid octet)
                ((<= #xdc80 code #xdcff)
                 (set-octet 0 (f-logand code #xff))
-                (incf di))
+                (f-incf di))
                ;; 3 octets
                ((< code #x10000)
-                (set-octet 0 (logior #xe0 (f-ash code -12)))
-                (set-octet 1 (logior #x80 (f-logand #x3f (f-ash code -6))))
-                (set-octet 2 (logior #x80 (f-logand code #x3f)))
-                (incf di 3))
+                (set-octet 0 (f-logior #xe0 (f-ash code -12)))
+                (set-octet 1 (f-logior #x80 (f-logand #x3f (f-ash code -6))))
+                (set-octet 2 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 3))
                ;; 4 octets
                (t
-                (set-octet 0 (logior #xf0 (f-logand #x07 (f-ash code -18))))
-                (set-octet 1 (logior #x80 (f-logand #x3f (f-ash code -12))))
-                (set-octet 2 (logior #x80 (f-logand #x3f (f-ash code -6))))
-                (set-octet 3 (logand #x3f code))
-                (incf di 4))))
-           finally (return (the fixnum (- di d-start))))))
+                (set-octet 0 (f-logior #xf0 (f-logand #x07 (f-ash code -18))))
+                (set-octet 1 (f-logior #x80 (f-logand #x3f (f-ash code -12))))
+                (set-octet 2 (f-logior #x80 (f-logand #x3f (f-ash code -6))))
+                (set-octet 3 (f-logand #x3f code))
+                (f-incf di 4))))
+           finally (return (f-- di d-start)))))
 
 (define-decoder :utf-8b (getter src-type setter dest-type)
   `(named-lambda utf-8b-decoder (src start end dest d-start)
@@ -441,15 +497,15 @@ code points for each invalid byte."
              ;; garbage.
              (macrolet
                  ((consume-octet (n)
-                    `(if (= i (1- end))
-                         (encode-raw-octets ,n)
-                         (,',getter src (incf i))))
+                    `(the fixnum (if (= i (1- end))
+                                   (encode-raw-octets ,n)
+                                   (,',getter src (f-incf i)))))
                   (encode-raw-octets (n)
                     `(progn
                        ,@(loop for i below n and var in '(u1 u2 u3 u4)
-                               collect `(,',setter (logior #xdc00 ,var) dest di)
+                               collect `(,',setter (f-logior #xdc00 ,var) dest di)
                                unless (= i (1- n))
-                               collect '(incf di))
+                               collect '(f-incf di))
                        (return-from set-body))))
                (block set-body
                  (,setter (cond
@@ -460,8 +516,8 @@ code points for each invalid byte."
                              (cond
                                ((< u1 #xe0) ; 2 octets
                                 (if (< (f-logxor u2 #x80) #x40)
-                                    (logior (f-ash (f-logand #x1f u1) 6)
-                                            (f-logxor u2 #x80))
+                                    (f-logior (f-ash (f-logand #x1f u1) 6)
+                                              (f-logxor u2 #x80))
                                     (encode-raw-octets 2)))
                                (t
                                 (setq u3 (consume-octet 2))
@@ -474,7 +530,7 @@ code points for each invalid byte."
                                                               (f-ash (f-logand u2 #x3f) 6))))
                                          (if (<= #xd800 start #xdfc0)
                                              (encode-raw-octets 3)
-                                             (logior start (f-logand u3 #x3f))))
+                                             (f-logior start (f-logand u3 #x3f))))
                                        (encode-raw-octets 3)))
                                   (t    ; 4 octets
                                    (setq u4 (consume-octet 3))
@@ -482,7 +538,7 @@ code points for each invalid byte."
                                             (< (f-logxor u3 #x80) #x40)
                                             (< (f-logxor u4 #x80) #x40)
                                             (or (>= u1 #xf1) (>= u2 #x90)))
-                                       (logior
+                                       (f-logior
                                         (f-logior (f-ash (f-logand u1 7) 18)
                                                   (f-ash (f-logxor u2 #x80) 12))
                                         (f-logior (f-ash (f-logxor u3 #x80) 6)
@@ -490,7 +546,229 @@ code points for each invalid byte."
                                        (encode-raw-octets 4)))))))
                             (t (encode-raw-octets 1)))
                           dest di)))
-             finally (return (the fixnum (- di d-start)))))))
+             finally (return (f-- di d-start))))))
+
+;;;; CESU-8
+
+(define-character-encoding :cesu-8
+    "An 8-bit, variable-length character encoding in which
+character code points in the range #x00-#x7f can be encoded in a
+single octet; characters with larger code values can be encoded
+in 2, 3, or 4 bytes.  It is the same as UTF-8 for code points < #x10000.
+For larger code points, it works as if the corresponding surrogate pair
+were encoded using UTF-8 rules."
+  :max-units-per-char 6
+  :literal-char-code-limit #x80
+  :default-replacement #xfffd)
+
+(define-octet-counter :cesu-8 (getter type)
+  `(lambda (seq start end max)
+     (declare (type ,type seq) (fixnum start end max))
+     (loop with noctets fixnum = 0
+           for i fixnum from start below end
+           for code of-type code-point = (,getter seq i) do
+           (let ((new (f-+ (cond ((< code #x80) 1)
+                                 ((< code #x800) 2)
+                                 ((< code #x10000) 3)
+                                 (t 6))
+                           noctets)))
+             (declare (type fixnum new))
+             (if (and (plusp max) (> new max))
+               (loop-finish)
+               (setq noctets new)))
+           finally (return (values noctets i)))))
+
+(define-condition invalid-cesu8-surrogate-sequence (character-decoding-error)
+  ()
+  (:documentation
+   "Signalled when the byte sequence for a high surrogate is not immediately followed by the byte sequence for a low surrogate."))
+
+;; The :utf-8 decoder goes to some trouble to distinguish overlong-utf8-sequence from
+;; character-out-of-range.  That seems silly, so we don't do it here.
+(define-condition invalid-cesu8-starter-byte (character-decoding-error)
+  ()
+  (:documentation
+   "Signalled when a 4- or greater byte sequence is encountered"))
+
+(define-code-point-counter :cesu-8 (getter type)
+  `(lambda (seq start end max)
+     (declare (type ,type seq) (fixnum start end max))
+     (loop with nchars fixnum = 0
+           with i fixnum = start
+           while (< i end) do
+           ;; check for invalid continuation bytes
+           (macrolet ((invalid-cb-p (n)
+                        `(and (< (f-+ i ,n) end)
+                              (not (< #x7f (the fixnum (,',getter seq (f-+ i ,n))) #xc0)))))
+             ;; wrote this code with LET instead of FOR because CLISP's
+             ;; LOOP doesn't like WHILE clauses before FOR clauses.
+             (let* ((octet (,getter seq i))
+                    (next-i (f-+ i (cond ((or (< octet #xc0) (invalid-cb-p 1)) 1)
+                                         ((or (< octet #xe0) (invalid-cb-p 2)) 2)
+                                         ((= octet #xed)
+                                          (if (and (< (f-+ i 5) end)
+                                                   (<= #xa0 (,getter seq (f-+ i 1)) #xaf) ; high surrogate
+                                                   (= (,getter seq (f-+ i 3)) #xed)
+                                                   (<= #xb0 (,getter seq (f-+ i 4)) #xbf) ; low surrogate
+                                                   (< #x7f (,getter seq (f-+ i 5)) #xc0)) ; continuation byte
+                                            6
+                                            3))
+                                         ((or (< octet #xf0) (invalid-cb-p 3)) 3)
+                                         ((or (< octet #xf8) (invalid-cb-p 4)) 4)
+                                         ((or (< octet #xfc) (invalid-cb-p 5)) 5)
+                                         (t 6)))))
+               (declare (type ub8 octet) (fixnum next-i))
+               (cond
+                 ((> next-i end)
+                  ;; Should we add restarts to this error, we'll have
+                  ;; to figure out a way to communicate with the
+                  ;; decoder since we probably want to do something
+                  ;; about it right here when we have a chance to
+                  ;; change the count or something.  (Like an
+                  ;; alternative replacement character or perhaps the
+                  ;; existence of this error so that the decoder
+                  ;; doesn't have to check for it on every iteration
+                  ;; like we do.)
+                  ;;
+                  ;; FIXME: The data for this error is not right.
+                  (decoding-error (vector octet) :cesu-8 seq i
+                                  nil 'end-of-input-in-character)
+                  (return (values (f-1+ nchars) end)))
+                 (t
+                  (setq nchars (f-1+ nchars)
+                        i next-i)
+                  (when (and (plusp max) (= nchars max))
+                    (return (values nchars i)))))))
+           finally (progn
+                     (assert (= i end))
+                     (return (values nchars i))))))
+
+(define-encoder :cesu-8 (getter src-type setter dest-type)
+  `(lambda (src start end dest d-start)
+     (declare (type ,src-type src)
+              (type ,dest-type dest)
+              (fixnum start end d-start))
+     (loop with di fixnum = d-start
+           for i fixnum from start below end
+           for code of-type code-point = (,getter src i) do
+           (macrolet ((set-octet (offset value)
+                        `(,',setter ,value dest (f-+ di ,offset))))
+             (cond
+               ;; 1 octet
+               ((< code #x80)
+                (set-octet 0 code)
+                (f-incf di))
+               ;; 2 octets
+               ((< code #x800)
+                (set-octet 0 (f-logior #xc0 (f-ash code -6)))
+                (set-octet 1 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 2))
+               ;; 3 octets
+               ((< code #x10000)
+                (set-octet 0 (f-logior #xe0 (f-ash code -12)))
+                (set-octet 1 (f-logior #x80 (f-logand #x3f (f-ash code -6))))
+                (set-octet 2 (f-logior #x80 (f-logand code #x3f)))
+                (f-incf di 3))
+               ;; 6 octets
+               (t
+                (let ((scode (- code #x10000)))
+                  (declare (type (mod #x100000) scode))
+                  ;; make the UTF-16 surrogate pair, then put out each
+                  ;; surrogate code point out as UTF-8
+                  ;; high surrogate is (f-logior #xd800 (ldb (byte 10 10) scode))
+                  ;; low surrogate is (f-logior #xdc00 (ldb (byte 10 0) scode))
+                  (set-octet 0 #.(f-logior #xe0 (ldb (byte 4 12) #xd800)))
+                  (set-octet 1 (f-logior #.(f-logior #x80 (ldb (byte 6 6) #xd800))
+                                       (f-logand #x0f (f-ash scode -16))))
+                  (set-octet 2 (f-logior #x80 (f-logand #x3f (f-ash scode -10))))
+                  (set-octet 3 #.(f-logior #xe0 (ldb (byte 4 12) #xdc00)))
+                  (set-octet 4 (f-logior #.(f-logior #x80 (ldb (byte 6 6) #xdc00))
+                                         (f-logand #x0f (f-ash scode -6))))
+                  (set-octet 5 (f-logior #x80 (f-logand #x3f scode)))
+                  (f-incf di 6)))))
+           finally (return (f-- di d-start)))))
+
+(define-decoder :cesu-8 (getter src-type setter dest-type)
+  `(lambda (src start end dest d-start)
+     ;; Note:  This reuses the UTF-8 error conditions.  Change that if you like.
+     (declare (type ,src-type src)
+              (type ,dest-type dest)
+              (fixnum start end d-start))
+     (let ((u2 0) (u3 0) (u4 0) (u5 0) (u6 0))
+       (declare (type ub8 u2 u3 u4 u5 u6))
+       (loop for di fixnum from d-start
+             for i fixnum from start below end
+             for u1 of-type ub8 = (,getter src i) do
+             ;; Note: CONSUME-OCTET doesn't check if I is being
+             ;; incremented past END.  We're assuming that END has
+             ;; been calculated with the CODE-POINT-POINTER above that
+             ;; checks this.
+             (macrolet
+                 ((consume-octet ()
+                    `(let ((next-i (f-incf i)))
+                       (if (= next-i end)
+                           ;; FIXME: data for this error is incomplete.
+                           ;; and signalling this error twice
+                           (return-from setter-block
+                             (decoding-error nil :cesu-8 src i +repl+
+                                             'end-of-input-in-character))
+                           (,',getter src next-i))))
+                  (handle-error (n &optional (c 'character-decoding-error))
+                    `(decoding-error
+                      (vector ,@(subseq '(u1 u2 u3 u4 u5 u6) 0 n))
+                      :cesu-8 src (1+ (- i ,n)) +repl+ ',c))
+                  (handle-error-if-icb (var n)
+                    `(when (not (< #x7f ,var #xc0))
+                       (decf i)
+                       (return-from setter-block
+                         (handle-error ,n invalid-utf8-continuation-byte)))))
+               (,setter
+                (block setter-block
+                  (cond
+                    ((< u1 #x80) u1)    ; 1 octet
+                    ((< u1 #xc0)
+                     (handle-error 1 invalid-utf8-starter-byte))
+                    (t
+                     (setq u2 (consume-octet))
+                     (handle-error-if-icb u2 1)
+                     (cond
+                       ((< u1 #xc2)
+                        (handle-error 2 overlong-utf8-sequence))
+                       ((< u1 #xe0)     ; 2 octets
+                        (f-logior (f-ash (f-logand #x1f u1) 6)
+                                  (f-logxor u2 #x80)))
+                       (t
+                        (setq u3 (consume-octet))
+                        (handle-error-if-icb u3 2)
+                        (cond
+                          ((and (= u1 #xe0) (< u2 #xa0))
+                           (handle-error 3 overlong-utf8-sequence))
+                          ((and (= u1 #xed) (<= #xa0 u2))
+                           (cond ((< u2 #xb0)
+                                  (setq u4 (consume-octet))
+                                  (unless (= u4 #xed)
+                                    (handle-error 4 invalid-cesu8-surrogate-sequence))
+                                  (setq u5 (consume-octet))
+                                  (handle-error-if-icb u5 4)
+                                  (when (< u5 #xb0)
+                                    (handle-error 5 invalid-cesu8-surrogate-sequence))
+                                  (setq u6 (consume-octet))
+                                  (handle-error-if-icb u6 5)
+                                  (the (unsigned-byte 21)
+                                    (f-+ #x10000
+                                         (f-logior (f-ash (f-logand u2 #x0f) 16)
+                                                   (f-ash (f-logand u3 #x3f) 10)
+                                                   (f-ash (f-logand u5 #x0f) 6)
+                                                   (f-logand u6 #x3f)))))
+                                 (t (handle-error 3 invalid-utf-8-continuation-byte-sequence))))
+                          ((< u1 #xf0)  ; 3 octets
+                           (f-logior (f-ash (f-logand u1 #x0f) 12)
+                                     (f-logior (f-ash (f-logand u2 #x3f) 6)
+                                               (f-logand u3 #x3f))))
+                          (t            ; 4 octets
+                           (handle-error 1 invalid-cesu8-starter-byte))))))))
+                dest di))
+             finally (return (f-- di d-start))))))
 
 ;;;; UTF-16
 
@@ -503,7 +781,7 @@ code points for each invalid byte."
      (loop with noctets fixnum = 0
            for i fixnum from start below end
            for code of-type code-point = (,getter seq i)
-           do (let ((new (the fixnum (+ (if (< code #x10000) 2 4) noctets))))
+           do (let ((new (f-+ (if (< code #x10000) 2 4) noctets)))
                 (if (and (plusp max) (> new max))
                     (loop-finish)
                     (setq noctets new)))
@@ -511,13 +789,13 @@ code points for each invalid byte."
 
 (defmacro utf-16-combine-surrogate-pairs (u1 u2)
   `(the (unsigned-byte 21)
-     (+ #x10000
-        (the (unsigned-byte 20)
-          (logior
-           (the (unsigned-byte 20)
-             (ash (the (unsigned-byte 10) (- ,u1 #xd800)) 10))
-           (the (unsigned-byte 10)
-             (- ,u2 #xdc00)))))))
+     (f-+ #x10000
+          (the (unsigned-byte 20)
+            (f-logior
+             (the (unsigned-byte 20)
+               (ash (the (unsigned-byte 10) (- ,u1 #xd800)) 10))
+             (the (unsigned-byte 10)
+               (- ,u2 #xdc00)))))))
 
 (defmacro define-utf-16 (name &optional endianness)
   (check-type endianness (or null (eql :be) (eql :le)))
diff --git a/src/encodings.lisp b/src/encodings.lisp
index da2c66b..e87c323 100644
--- a/src/encodings.lisp
+++ b/src/encodings.lisp
@@ -24,10 +24,13 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/packages")))
+
 (in-package #:babel-encodings)
 
 ;;;; Character Encodings
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
 (defclass character-encoding ()
   ((name :initarg :name :reader enc-name
          :initform (error "Must specify a NAME for this character encoding."))
@@ -80,6 +83,7 @@
           literal-char-code-limit)
     (setf (slot-value enc 'decode-literal-code-unit-limit)
           literal-char-code-limit)))
+) ;; end EVAL-WHEN
 
 #-(and)
 (defmethod describe-object ((enc character-encoding) s)
@@ -92,6 +96,7 @@ character encoding object."
     (format s "~&~A~%~%" documentation))
   (call-next-method))
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
 (defvar *supported-character-encodings* nil)
 
 (defun list-character-encodings ()
@@ -204,6 +209,7 @@ a CHARACTER-ENCONDING object, it is returned unmodified."
       (setq mapping (make-instance 'abstract-mapping))
       (setf (get-abstract-mapping encoding) mapping))
     (setf (slot-value mapping slot-name) fn)))
+) ;; end EVAL-WHEN
 
 ;;; See enc-*.lisp for example usages of these 4 macros.
 
@@ -227,6 +233,7 @@ a CHARACTER-ENCONDING object, it is returned unmodified."
                            (named-lambda code-point-counter (,acc ,type)
                              ,@body)))
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
 (defun instantiate-encoder (encoding am octet-seq-getter octet-seq-type
                             code-point-seq-setter code-point-seq-type)
   (declare (ignore encoding))
@@ -260,6 +267,7 @@ a CHARACTER-ENCONDING object, it is returned unmodified."
       (funcall (octet-counter-factory am)
                code-point-seq-getter
                code-point-seq-type)))
+) ;; end EVAL-WHEN
 
 ;;; Expands into code generated by the available abstract mappings
 ;;; that will be compiled into concrete mappings.  This is used in
@@ -349,8 +357,12 @@ a CHARACTER-ENCONDING object, it is returned unmodified."
 ;;; We're converting between objects of the (UNSIGNED-BYTE 8) and
 ;;; (MOD #x110000) types which are aliased here to UB8 and CODE-POINT
 ;;; for convenience.
-(deftype ub8 () '(unsigned-byte 8))
-(deftype code-point () '(mod #x110000))
+(deftype ub8        () '(unsigned-byte 8))
+
+;;; For speed, make this type simply be fixnum, even
+;;; though that is not the Right Thing. -- SWM and DLW, March 2009.
+;;;(deftype code-point () '(mod #x110000))
+(deftype code-point () 'fixnum)
 
 ;;; Utility macro around DEFINE-ENCODER that takes care of most of the
 ;;; work need to deal with an 8-bit, fixed-width character encoding.
diff --git a/src/external-format.lisp b/src/external-format.lisp
index 62bb919..ca15d01 100644
--- a/src/external-format.lisp
+++ b/src/external-format.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/packages" "src/encodings")))
+
 (in-package #:babel)
 
 (defvar *default-eol-style*
diff --git a/src/gbk-map.lisp b/src/gbk-map.lisp
index 5b7eb4f..32112e4 100644
--- a/src/gbk-map.lisp
+++ b/src/gbk-map.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/packages")))
+
 (in-package #:babel-encodings)
 
 (defparameter *gbk-unicode-mapping*
diff --git a/src/jpn-table.lisp b/src/jpn-table.lisp
index f0cf849..396923f 100644
--- a/src/jpn-table.lisp
+++ b/src/jpn-table.lisp
@@ -3,6 +3,8 @@
 ;;; jpn-table.lisp --- Unicode tables for Japanese encodings.
 ;;;
 
+#+xcvb (module (:depends-on ("src/packages")))
+
 (in-package #:babel-encodings)
 
 (defvar *cp932-only*
diff --git a/src/packages.lisp b/src/packages.lisp
index ace36e8..68b8489 100644
--- a/src/packages.lisp
+++ b/src/packages.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module ())
+
 (in-package #:cl-user)
 
 (defpackage #:babel-encodings
diff --git a/src/sharp-backslash.lisp b/src/sharp-backslash.lisp
index d4e772e..bad3b5b 100644
--- a/src/sharp-backslash.lisp
+++ b/src/sharp-backslash.lisp
@@ -24,6 +24,8 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb (module (:depends-on ("src/packages")))
+
 (in-package #:babel)
 
 #-allegro
diff --git a/src/streams.lisp b/src/streams.lisp
index e4562bb..cce2751 100644
--- a/src/streams.lisp
+++ b/src/streams.lisp
@@ -42,6 +42,8 @@
 ;;;   output streams
 ;;; - in-memory input/output streams?
 
+#+xcvb (module (:depends-on ("/babel")))
+
 (in-package #:babel)
 
 (defpackage #:babel-streams
diff --git a/src/strings.lisp b/src/strings.lisp
index ba02089..016c2fc 100644
--- a/src/strings.lisp
+++ b/src/strings.lisp
@@ -24,6 +24,16 @@
 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 ;;; DEALINGS IN THE SOFTWARE.
 
+#+xcvb
+(module
+ (:depends-on ("src/encodings"
+               "src/enc-unicode"
+               "src/enc-ascii"
+               "src/external-format")
+  :compile-depends-on ("src/encodings"
+                       "src/enc-unicode"
+                       "src/enc-ascii")))
+
 (in-package #:babel)
 
 ;;; The usefulness of this string/octets interface of Babel's is very
