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

Gio*_*gio 6 sbcl common-lisp

我试图使用SBCL 1.1.7在Ubuntu 12.04上从命令行运行一个通用的lisp脚本.我用脚本启动脚本

$ sbcl --script <my-script.lisp>
Run Code Online (Sandbox Code Playgroud)

由于脚本是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.
Run Code Online (Sandbox Code Playgroud)

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

任何提示?

Jos*_*lor 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))))))
Run Code Online (Sandbox Code Playgroud)

看起来文件是打开的(with-open-file (f (native-pathname script) :element-type :default) …).根据usockets的答案:当我打开套接字时,如何指定外部格式,默认编码应为UTF-8,快速交互式测试似乎确认:

CL-USER> sb-impl::*default-external-format*
:UTF-8
Run Code Online (Sandbox Code Playgroud)

但是,根据处理选项的顺序,您可以执行的操作是在处理脚本之前使用--eval选项进行设置sb-impl::*default-external-format*.例如,命令行如:

$ sbcl --eval '(setf sb-impl::*default-external-format* …)' --script my-script.lisp
Run Code Online (Sandbox Code Playgroud)

但是,那就是说,我根本不确定是否支持.根据comp.lang.lisp上的一个帖子,如何更改SBCL中的外部格式(c-string编码错误),默认编码是通过检查环境来确定的,因此环境中可能有一些东西你可以做到获取您需要的编码作为默认值.该线程中的一个响应表明以下内容可能有效:

$ LC_CTYPE=en_US.UTF-8 
$ export LC_CTYPE
$ sbcl --script my-script.lisp
Run Code Online (Sandbox Code Playgroud)