common-lisp - 使用 Steel Bank Common Lisp 运行 utf-8 编码的脚本

标签 common-lisp sbcl

我试图在 Ubuntu 12.04 上使用 SBCL 1.1.7 从命令行运行一个通用的 lisp 脚本。我开始脚本

$ sbcl --script <my-script.lisp>

由于脚本是 UTF_8 编码的,我收到一些错误消息:
; compiling (DEFUN PRINT-USAGE ...)unhandled SB-INT:STREAM-DECODING-ERROR in thread #<SB-THREAD:THREAD
                                               "main thread" RUNNING
                                                {1002A39983}>:
:ASCII stream decoding error on
#<SB-SYS:FD-STREAM
    for "file ... .lisp"
    {10045745E3}>:

    the octet sequence #(194) cannot be decoded.

我想解决方案是告诉 SBCL 将源文件视为 UTF-8,但我在文档或谷歌上找不到任何关于如何执行此操作的内容。

任何提示?

最佳答案

我不是一个 SBCL 黑客,但看着 toplevel.lisp ,看来处理 --script 的代码是:

(defun process-script (script)
  (flet ((load-script (stream)
           ;; Scripts don't need to be stylish or fast, but silence is usually a
           ;; desirable quality...
           (handler-bind (((or style-warning compiler-note) #'muffle-warning)
                          (stream-error (lambda (e)
                                          ;; Shell-style.
                                          (when (member (stream-error-stream e)
                                                        (list *stdout* *stdin* *stderr*))
                                            (exit)))))
             ;; Let's not use the *TTY* for scripts, ok? Also, normally we use
             ;; synonym streams, but in order to have the broken pipe/eof error
             ;; handling right we want to bind them for scripts.
             (let ((*terminal-io* (make-two-way-stream *stdin* *stdout*))
                   (*debug-io* (make-two-way-stream *stdin* *stderr*))
                   (*standard-input* *stdin*)
                   (*standard-output* *stdout*)
                   (*error-output* *stderr*))
               (load stream :verbose nil :print nil)))))
    (handling-end-of-the-world
      (if (eq t script)
          (load-script *stdin*)
          (with-open-file (f (native-pathname script) :element-type :default)
            (sb!fasl::maybe-skip-shebang-line f)
            (load-script f))))))

看起来文件是用 (with-open-file (f (native-pathname script) :element-type :default) …) 打开的.根据对usockets: How do I specify the external format when I open a socket的回答,默认编码应该是 UTF-8,一个快速的交互测试似乎可以确认:
CL-USER> sb-impl::*default-external-format*
:UTF-8

但是,根据处理选项的顺序,您可能可以使用 --eval设置选项 sb-impl::*default-external-format*在处理脚本之前。例如,像这样的命令行:
$ sbcl --eval '(setf sb-impl::*default-external-format* …)' --script my-script.lisp

但是,话虽如此,我完全不确定这是否受支持。根据 comp.lang.lisp 上的一个线程,How to change external-format in SBCL (c-string encoding error) ,默认编码是通过检查环境来确定的,因此您可以在环境中执行某些操作来获取您需要的默认编码。该线程中的一个响应表明以下可能有效:
$ LC_CTYPE=en_US.UTF-8 
$ export LC_CTYPE
$ sbcl --script my-script.lisp

关于common-lisp - 使用 Steel Bank Common Lisp 运行 utf-8 编码的脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22822793/

相关文章:

common-lisp - 长整数到字符串,反之亦然,用数字运算

lisp - 定义我自己的读取宏

recursion - Lisp - 拆分递归

lisp - 如何将列表列表传递给函数?

common-lisp - 如何在 Common Lisp 中将字节数组转换为字符串?

command-line - 编写从命令行执行但不在解释器内部执行的Common Lisp代码

lisp - 口齿不清错误 : Expected-type: REAL datum: NIL

lisp - Slime:frame-source-location 未实现/我的 sldb Backtrace 输出是否正常?

common-lisp - 在Common Lisp中,如何定义通用数据类型说明符(如整数列表)?

lisp - 如何检测输入流是否为空(但不是 EOF)?