Запуск скриптов в кодировке utf-8 с помощью Steel Bank Common Lisp

Я пытаюсь запустить общий скрипт lisp из командной строки в Ubuntu 12.04, используя SBCL 1.1.7. Я запускаю скрипт с

$ 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, но я не могу найти ничего в документации или в Google о том, как это сделать.

Любой намек?


person Giorgio    schedule 02.04.2014    source источник


Ответы (1)


Я не большой хакер 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: как указать внешний формат при открытии сокета, кодировка по умолчанию должна быть 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, Как изменить внешний формат в SBCL (ошибка кодирования c-строки), кодировка по умолчанию определяется путем изучения среды, поэтому в среде может быть что-то, что вы можете сделать, чтобы получить кодировку, которая вам нужна в качестве По умолчанию. Один ответ в этой теме указывает, что может работать следующее:

$ LC_CTYPE=en_US.UTF-8 
$ export LC_CTYPE
$ sbcl --script my-script.lisp
person Joshua Taylor    schedule 02.04.2014
comment
Установка sb-impl::*default-external-format* перед загрузкой основного файла приложения работает. Большое спасибо! - person Giorgio; 13.04.2014
comment
Я сделал sbcl -- eval '(setf sb-impl::*default-external-format* :UTF-8)' с успехом на Mac OSX Yosemite, потому что это было US-ASCII с самого начала. Орг-бабельная слизь тоже автоматически сделала это за меня. - person Reb.Cabin; 09.01.2016