Emacs 30.2 にしたら起動時 tamago-tsunagi のエラーが出た
丁度ここと同じ状況になった。
当該記事は、パッチの在処迄記載しているので、これで直れば良かったのだが…
Emacs は起動するようになったが、漢字変換開始時にエラーが出る
Backtrace
Debugger entered--Lisp error: (wrong-type-argument obarrayp [nil nil nil nil nil])
signal(wrong-type-argument (obarrayp [nil nil nil nil nil]))
(condition-case err (let* ((proc (wnnenv-get-proc env)) (buffer (process-buffer proc)) (zhuyin its-zhuyin) (comm-accept-timeout wnnrpc-timeout) (env-id (wnnenv-get-env-id env)) file-id) (if (and (memq (process-status proc) '(open run)) (buffer-live-p buffer)) (save-current-buffer (set-buffer buffer) (let ((egg-fixed-euc (nth ... egg-fixed-euc))) (erase-buffer) (progn (comm-format-u32 99) (comm-format-u32 env-id) (comm-format-vector (nth 1 header) 28)) (goto-char (point-max)) (process-send-region proc (point-min) (point-max)) (progn (setq file-id (comm-unpack-i32))) (if (>= file-id 0) (let (result resulth) (progn ... ...) (cond ... ... ...) (if ... ... ... file-id)) (let (result resulth) (progn ... ...) (cond ... ... ...) (if ... ... ...))))) (egg-error "process %s was killed" proc))) ((quit error) (let* ((proc (wnnenv-get-proc env)) (buffer (process-buffer proc)) (zhuyin its-zhuyin) (comm-accept-timeout wnnrpc-timeout) (env-id (wnnenv-get-env-id env))) (if (and (memq (process-status proc) '(open run)) (buffer-live-p buffer)) (save-current-buffer (set-buffer buffer) (let ((egg-fixed-euc ...)) (erase-buffer) (progn (comm-format-u8-string "") (comm-format-binary-data "") (comm-format-binary-data "") (comm-format-binary-data "") (comm-format-binary-data "") (comm-format-binary-data "") (comm-format-binary-data "")) (goto-char (point-max)) (process-send-region proc (point-min) (point-max)))) (egg-error "process %s was killed" proc))) (signal (car err) (cdr err))))
(if (numberp header) header (condition-case err (let* ((proc (wnnenv-get-proc env)) (buffer (process-buffer proc)) (zhuyin its-zhuyin) (comm-accept-timeout wnnrpc-timeout) (env-id (wnnenv-get-env-id env)) file-id) (if (and (memq (process-status proc) '(open run)) (buffer-live-p buffer)) (save-current-buffer (set-buffer buffer) (let ((egg-fixed-euc ...)) (erase-buffer) (progn (comm-format-u32 99) (comm-format-u32 env-id) (comm-format-vector ... 28)) (goto-char (point-max)) (process-send-region proc (point-min) (point-max)) (progn (setq file-id ...)) (if (>= file-id 0) (let ... ... ... ...) (let ... ... ... ...)))) (egg-error "process %s was killed" proc))) ((quit error) (let* ((proc (wnnenv-get-proc env)) (buffer (process-buffer proc)) (zhuyin its-zhuyin) (comm-accept-timeout wnnrpc-timeout) (env-id (wnnenv-get-env-id env))) (if (and (memq (process-status proc) '...) (buffer-live-p buffer)) (save-current-buffer (set-buffer buffer) (let (...) (erase-buffer) (progn ... ... ... ... ... ... ...) (goto-char ...) (process-send-region proc ... ...))) (egg-error "process %s was killed" proc))) (signal (car err) (cdr err)))))
(let ((header (wnnrpc-check-local-file filename))) (if (numberp header) header (condition-case err (let* ((proc (wnnenv-get-proc env)) (buffer (process-buffer proc)) (zhuyin its-zhuyin) (comm-accept-timeout wnnrpc-timeout) (env-id (wnnenv-get-env-id env)) file-id) (if (and (memq (process-status proc) '...) (buffer-live-p buffer)) (save-current-buffer (set-buffer buffer) (let (...) (erase-buffer) (progn ... ... ...) (goto-char ...) (process-send-region proc ... ...) (progn ...) (if ... ... ...))) (egg-error "process %s was killed" proc))) ((quit error) (let* ((proc (wnnenv-get-proc env)) (buffer (process-buffer proc)) (zhuyin its-zhuyin) (comm-accept-timeout wnnrpc-timeout) (env-id (wnnenv-get-env-id env))) (if (and (memq ... ...) (buffer-live-p buffer)) (save-current-buffer (set-buffer buffer) (let ... ... ... ... ...)) (egg-error "process %s was killed" proc))) (signal (car err) (cdr err))))))
wnnrpc-file-send([#<process Wnn> 0 jserver wnn4 wnn-backend-Japanese nil <ユーザー名> [1 1]] "<辞書の絶対path>")
Wnn のリモート辞書
Wnn の辞書は、(jserver プロセスから見て)LOCALなものと、REMOTEなものの2種類が使える。
LOCAL辞書は jserver が動くマシン上に置かれる。
所有者は jserver プロセスと同じになる。
殆どの人はこれを使っていると思う。
REMOTE辞書は、(jserver プロセスから見て)クライアント側のマシンに置かれる。
所有者はクライアントのプロセスと同じになる、つまり自分。
私は、辞書を自分のホーム・ディレクトリに置きたいので、こっちを使っている。
…多分、このせいで wnnrpc-file-send が呼ばれて、そこでエラーになっているんじゃないのかな?
リモート辞書の指定方法
~/.eggrc で wnn-add-dict する時に、ファイル名(path name)冒頭に "!" を付けるだけ。辞書ファイル、頻度ファイル、双方共同様。
サンプルコード
;;;
(wnn-add-dict
(concat "!" (expand-file-name "~/.emacs.d/dic/temp-normal"))
""
3 t nil
(expand-file-name "~/.emacs.d/dic/<user>-password"))
wnnrpc-file-send のエラーを調べる
結局の所、intern の optional 引数の OBARRAY に vector が来てしまっているのがいけない。
Emacs 30 よりも前迄は、obarray には vector を使っていたけれども、Emacs 30 では obarray は vector では無くなったので、
make-vector ではなく
obarray-make を使わないといけない。
どう直す?
じゃなんで obarray / intern を使っていたのか?
どう見ても、kvp で管理したいものがあったけれども、昔は hashtable が使えなかったから?
tamago-tsunagi の全貌が理解できていないので、仕方が無いので、自分の使い方で実行してエラーになる箇所だけ、hash-table で書き換えてみた。今のところ、問題なく動いている。
パッチはこちら
hash-table を使ったパッチ
diff -Buar tamago-tsunagi-5.0.7.1/egg/wnn.el /usr/local/share/emacs/site-lisp/tamago-tsunagi/egg/wnn.el
--- tamago-tsunagi-5.0.7.1/egg/wnn.el 2026-04-18 11:00:39.574476401 +0900
+++ /usr/local/share/emacs/site-lisp/tamago-tsunagi/egg/wnn.el 2026-04-18 04:42:31.985345579 +0900
@@ -367,9 +367,13 @@
(defun wnnenv-create (proc env-id &optional server-type wnn-version
backend tankan name)
- (if name
- (set (setq name (make-symbol name)) (make-vector 5 nil)))
- (vector proc env-id server-type wnn-version backend tankan name
+ ;; env[6] = env-name-kvp
+ ;; env-name-kvp = (env-name, kvp)
+;; (if name
+;; (set (setq name (make-symbol name)) (make-vector 5 nil)))
+ (vector proc env-id server-type wnn-version backend tankan
+;; name
+ (cons name (make-hash-table :size 5 :test 'equal))
(make-vector 2 (WNN-const DIC_RDONLY))))
(defsubst wnnenv-get-proc (env) (aref env 0))
@@ -379,16 +383,28 @@
(defsubst wnnenv-get-backend (env) (aref env 4))
(defsubst wnnenv-get-tankan (env) (aref env 5))
+;;; env[6] = (env-name . kvp)
(defun wnnenv-get-client-file (env name)
- (let ((hash (intern-soft name (symbol-value (aref env 6)))))
- (and hash (symbol-value hash))))
+;; (let ((hash (intern-soft name (symbol-value (aref env 6)))))
+;; (and hash (symbol-value hash)))
+ (gethash name (cdr (aref env 6)))
+)
(defun wnnenv-set-client-file (env name)
- (set (intern (concat wnn-system-name "!" name) (symbol-value (aref env 6)))
- name))
-
-(defsubst wnnenv-get-hinshi (env h) (or (get (aref env 6) h) -1))
-(defsubst wnnenv-set-hinshi (env h v) (put (aref env 6) h v))
+;; (set (intern (concat wnn-system-name "!" name) (symbol-value (aref env 6)))
+;; name)
+ (puthash (concat wnn-system-name "!" name) name (cdr (aref env 6)))
+)
+
+(defsubst wnnenv-get-hinshi (env h)
+ (or
+;; (get (aref env 6) h)
+ (gethash h (cdr (aref env 6)))
+ -1))
+(defsubst wnnenv-set-hinshi (env h v)
+;; (put (aref env 6) h v)
+ (puthash h v (cdr (aref env 6)))
+ )
(defsubst wnnenv-get-auto-learn (env) (aref env 7))
(defsubst wnnenv-get-notrans (env) (aref (wnnenv-get-auto-learn env) 0))
diff -Buar tamago-tsunagi-5.0.7.1/egg.el /usr/local/share/emacs/site-lisp/tamago-tsunagi/egg.el
--- tamago-tsunagi-5.0.7.1/egg.el 2015-02-03 07:22:57.000000000 +0900
+++ /usr/local/share/emacs/site-lisp/tamago-tsunagi/egg.el 2026-04-18 05:21:48.835162069 +0900
@@ -30,7 +30,7 @@
;;; Code:
-(defconst egg-version "5.0.7.1"
+(defconst egg-version "5.0.7.1a"
"Version number for this version of Tamago.")
(defconst egg-tsunagi-version egg-version
diff -Buar tamago-tsunagi-5.0.7.1/its.el /usr/local/share/emacs/site-lisp/tamago-tsunagi/its.el
--- tamago-tsunagi-5.0.7.1/its.el 2026-04-18 11:02:23.347253213 +0900
+++ /usr/local/share/emacs/site-lisp/tamago-tsunagi/its.el 2026-04-18 02:09:37.286123001 +0900
@@ -1355,8 +1355,8 @@
(interactive)
(its-convert (lambda (str lang) (japanese-katakana str))))
-(defconst its-full-half-table (make-vector 100 nil))
-(defconst its-half-full-table (make-vector 100 nil))
+(defconst its-full-half-table (make-hash-table :size 100))
+(defconst its-half-full-table (make-hash-table :size 100))
(let ((table '((Japanese
(? . ?\ ) (?, . ?,) (?. . ?.) (?、 . ?,) (?。 . ?.)
@@ -1466,20 +1466,23 @@
(?p . ?p) (?q . ?q) (?r . ?r) (?s . ?s) (?t . ?t)
(?u . ?u) (?v . ?v) (?w . ?w) (?x . ?x) (?y . ?y)
(?z . ?z))))
- (hash (make-vector 100 nil))
+;; (hash (make-vector 100 nil))
lang pair)
(while table
(setq lang (caar table)
pair (cdar table)
table (cdr table))
(while pair
- (set (intern (char-to-string (caar pair)) its-full-half-table)
- (cdar pair))
- (set (intern (concat (symbol-name lang) (char-to-string (cdar pair)))
- its-half-full-table)
- (caar pair))
+;; (set (intern (char-to-string (caar pair)) its-full-half-table)
+;; (cdar pair))
+ (puthash (caar pair) (cdar pair) its-full-half-table)
+;; (set (intern (concat (symbol-name lang) (char-to-string (cdar pair)))
+;; its-half-full-table)
+;; (caar pair))
+ (puthash (cdar pair) (caar pair) its-half-full-table)
(setq pair (cdr pair)))
- hash))
+;; hash
+ ))
;;; its-half-width : half-width-region for input-buffer
(defun its-half-width ()
他に気になること
現在、辞書の編集を行いたい場合は、次の手順を実施している。
- Emacs で wnn-close で辞書を閉じて、
- サーバー側では wnnstat -F で辞書が open されていないことを確認してから、
- ローカル側で、dtoa で現在の辞書をテキスト・ファイルに export し、
- 必要な編集を加えた後に、atod で辞書ファイルに書き戻し
本来なら、Emacs で egg-toroku-region すれば、少なくとも単語の追加は実行中に可能な筈なのだけれど…
少なくともリモート辞書を使っていると、辞書はしっかり壊れてしまう。egg-toroku-region を実行直後は、一見ちゃんと登録できているように見えるのだけれど。
この症状は大昔から解消できていない。どこでそうなってしまっているのかも分からないまま。
FreeWnn / tamago-tsunagi 双方共、Unicode で書き直してしまえば、もう少し見通しが良くなるのかもしれないけれど。
(追記) セットアップ
セットアップを書き忘れた。
- FreeWnn は、サービス化済み。手順はこちら。
- tamago-tsunagi は、/usr/local/share/emacs/site-lisp/tamago-tsunagi として配置。これは、Fedora Silverblue を使っているので、/usr/share/emacs/site-lisp には置けない為。
- 必要な load-path は、.emacs / site-start.el / default.el 等の初期化ファイルのどこかで設定。こんな感じで足して行く。
(add-to-list 'load-path "<ディレクトリ>")
load-path の値の例
("/usr/local/share/emacs/site-lisp"
"/usr/local/share/emacs/site-lisp/site-start.d"
"/usr/local/share/emacs/site-lisp/tamago-tsunagi"
"/usr/local/share/emacs/site-lisp/tamago-tsunagi/doc"
"/usr/local/share/emacs/site-lisp/tamago-tsunagi/egg"
"/usr/local/share/emacs/site-lisp/tamago-tsunagi/helper"
"/usr/local/share/emacs/site-lisp/tamago-tsunagi/its"
"/usr/local/share/emacs/site-lisp/tamago-tsunagi/doc/code-table"
"/usr/share/emacs/site-lisp/color-theme/"
"/usr/share/emacs/site-lisp/anthy-unicode"
"/usr/share/emacs/30.2/site-lisp" "/usr/share/emacs/site-lisp"
"/usr/share/emacs/site-lisp/anthy-unicode"
"/usr/share/emacs/site-lisp/apel"
"/usr/share/emacs/site-lisp/auto-complete"
"/usr/share/emacs/site-lisp/color-theme"
"/usr/share/emacs/site-lisp/desktop-file-utils"
"/usr/share/emacs/site-lisp/dockerfile-mode"
"/usr/share/emacs/site-lisp/goodies"
"/usr/share/emacs/site-lisp/json-mode"
"/usr/share/emacs/site-lisp/json-reformat"
"/usr/share/emacs/site-lisp/json-snatcher"
"/usr/share/emacs/site-lisp/mozc" "/usr/share/emacs/site-lisp/popup"
"/usr/share/emacs/site-lisp/s"
"/usr/share/emacs/site-lisp/site-start.d"
"/usr/share/emacs/site-lisp/spice-mode"
"/usr/share/emacs/site-lisp/yaml-mode"
"/usr/share/emacs/site-lisp/color-theme/themes"
"/usr/share/emacs/30.2/lisp" "/usr/share/emacs/30.2/lisp/vc"
"/usr/share/emacs/30.2/lisp/use-package"
"/usr/share/emacs/30.2/lisp/url"
"/usr/share/emacs/30.2/lisp/textmodes"
"/usr/share/emacs/30.2/lisp/progmodes"
"/usr/share/emacs/30.2/lisp/play" "/usr/share/emacs/30.2/lisp/org"
"/usr/share/emacs/30.2/lisp/nxml" "/usr/share/emacs/30.2/lisp/net"
"/usr/share/emacs/30.2/lisp/mh-e" "/usr/share/emacs/30.2/lisp/mail"
"/usr/share/emacs/30.2/lisp/leim"
"/usr/share/emacs/30.2/lisp/language"
"/usr/share/emacs/30.2/lisp/international"
"/usr/share/emacs/30.2/lisp/image" "/usr/share/emacs/30.2/lisp/gnus"
"/usr/share/emacs/30.2/lisp/eshell" "/usr/share/emacs/30.2/lisp/erc"
"/usr/share/emacs/30.2/lisp/emulation"
"/usr/share/emacs/30.2/lisp/emacs-lisp"
"/usr/share/emacs/30.2/lisp/cedet"
"/usr/share/emacs/30.2/lisp/calendar"
"/usr/share/emacs/30.2/lisp/calc"
"/usr/share/emacs/30.2/lisp/obsolete")
4. 旧版 Emacs から削除された関数を追加
/usr/local/share/emacs/site-lisp/site-start.d/prep-tamago-tsunagi.el として追加している。
prep-tamago-tsunagi.el
;;; tamago-tsunagi workaround, experimental
;;
;; adapt tamago-tsunagi to the latest emacs by mimicking obsolete functions
;;
(if (not (fboundp 'make-coding-system))
(defun make-coding-system (coding-system type mnemonic doc-string
&optional
flags
properties
eol-type)
"Define a new coding system CODING-SYSTEM (symbol).
This function is provided for backward compatibility."
(declare (obsolete define-coding-system "23.1"))
;; For compatibility with XEmacs, we check the type of TYPE. If it
;; is a symbol, perhaps, this function is called with XEmacs-style
;; arguments. Here, try to transform that kind of arguments to
;; Emacs style.
(if (symbolp type)
(let ((args (transform-make-coding-system-args coding-system type
mnemonic doc-string)))
(setq coding-system (car args)
type (nth 1 args)
mnemonic (nth 2 args)
doc-string (nth 3 args)
flags (nth 4 args)
properties (nth 5 args)
eol-type (nth 6 args))))
(setq type
(cond ((eq type 0) 'emacs-mule)
((eq type 1) 'shift-jis)
((eq type 2) 'iso2022)
((eq type 3) 'big5)
((eq type 4) 'ccl)
((eq type 5) 'raw-text)
(t
(error "Invalid coding system type: %s" type))))
(setq properties
(let ((plist nil) key)
(dolist (elt properties)
(setq key (car elt))
(cond ((eq key 'post-read-conversion)
(setq key :post-read-conversion))
((eq key 'pre-write-conversion)
(setq key :pre-write-conversion))
((eq key 'translation-table-for-decode)
(setq key :decode-translation-table))
((eq key 'translation-table-for-encode)
(setq key :encode-translation-table))
((eq key 'safe-charsets)
(setq key :charset-list))
((eq key 'mime-charset)
(setq key :mime-charset))
((eq key 'valid-codes)
(setq key :valids)))
(setq plist (plist-put plist key (cdr elt))))
plist))
(setq properties (plist-put properties :mnemonic mnemonic))
(plist-put properties :coding-type type)
(cond ((eq eol-type 0) (setq eol-type 'unix))
((eq eol-type 1) (setq eol-type 'dos))
((eq eol-type 2) (setq eol-type 'mac))
((vectorp eol-type) (setq eol-type nil)))
(plist-put properties :eol-type eol-type)
(cond
((eq type 'iso2022)
(plist-put properties :flags
(list (and (or (consp (nth 0 flags))
(consp (nth 1 flags))
(consp (nth 2 flags))
(consp (nth 3 flags))) 'designation)
(or (nth 4 flags) 'long-form)
(and (nth 5 flags) 'ascii-at-eol)
(and (nth 6 flags) 'ascii-at-cntl)
(and (nth 7 flags) '7-bit)
(and (nth 8 flags) 'locking-shift)
(and (nth 9 flags) 'single-shift)
(and (nth 10 flags) 'use-roman)
(and (nth 11 flags) 'use-oldjis)
(or (nth 12 flags) 'direction)
(and (nth 13 flags) 'init-at-bol)
(and (nth 14 flags) 'designate-at-bol)
(and (nth 15 flags) 'safe)
(and (nth 16 flags) 'latin-extra)))
(plist-put properties :designation
(let ((vec (make-vector 4 nil)))
(dotimes (i 4)
(let ((spec (nth i flags)))
(if (eq spec t)
(aset vec i '(94 96))
(if (consp spec)
(progn
(if (memq t spec)
(setq spec (append (delq t spec) '(94 96))))
(aset vec i spec))))))
vec)))
((eq type 'ccl)
(plist-put properties :ccl-decoder (car flags))
(plist-put properties :ccl-encoder (cdr flags))))
(apply 'define-coding-system coding-system doc-string properties)))
;;
;; https://www.mail-archive.com/users-jp@freebsd.org/msg00229.html
(define-obsolete-variable-alias
'inactivate-current-input-method-function
'deactivate-current-input-method-function
"24.3")
(define-obsolete-function-alias
'inactivate-input-method
'deactivate-input-method
"24.3")
;;
;; https://osdn.net/projects/tamago-tsunagi/ticket/48966
(if (not (fboundp 'buffer-has-markers-at))
(defun buffer-has-markers-at (position)
"Return t if there are markers pointing at POSITION in the current buffer.
The original function was obsolute since 24.3."
(let ((tmp-ring mark-ring))
(while (and tmp-ring
(not (= position (marker-position (car tmp-ring)))))
(pop tmp-ring)
)
tmp-ring)))
5. tamago-tsunagi の利用設定
/usr/local/share/emacs/site-lisp/default.el への追加 で実施している。
default.el 追記分
;;; languages input
;;
;;(load-file "/usr/share/emacs/30.2/lisp/leim/leim-list.el")
;; or
(load-file (concat source-directory "lisp/leim/leim-list.el"))
;; i.e. source-directory is defined in site-start.el
;;
;; tamago-tsunagi
;;
(if t
(progn
(load-file "/usr/local/share/emacs/site-lisp/tamago-tsunagi/leim-list.el")
(load-file "/usr/local/share/emacs/site-lisp/tamago-tsunagi/menudiag.el")
(setq default-input-method "japanese-egg-wnn")
;;
(custom-set-variables
;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
;; Your init file should contain only one such instance.
'(wnn-auto-save-dictionaries 19)
'(wnn-jserver '("localhost")))
;;
(setq toroku-region-yomigana "")
))
;;
;; alternately, use Anthy
;;
(if nil
(progn
(load-file "/usr/share/emacs/site-lisp/anthy-unicode/leim-list.el")
(setq default-input-method "japanese-anthy-unicode")))
辞書の変換 (追記 2026-04-21)
こんな便利なものがあるのに気付かず、自分で FreeWnn から Anthy への変換ツールを数時間かけて書いてしまいました。今度 ruby がインストールできたら、使ってみようと思います。複数のIME間で辞書を相互変換できるようです。
※ 2026-05-07
同ページに Wnn は未検証とある通り、実際には次のパッチが必要でした。
これは頻度情報出力の不足なので、dtoa の出力と /usr/bin/join して、Wnn 登録済単語について頻度情報を保存できると良いのですが…
userdic.patch
--- userdic.~1~ 2017-01-21 18:04:03.000000000 +0900
+++ userdic 2026-05-04 12:22:20.838887534 +0900
@@ -282,7 +282,10 @@
return nil if s == nil
pron, word, prop = s.split(/\t+/)
case type
- when 'generic', 'mozc', 'atok', 'msime', 'wnn'
+ when 'wnn'
+ prop = $hinshi_t[type][prop]
+ r = sprintf "%s\t%s\t%s\t0", pron, word, prop
+ when 'generic', 'mozc', 'atok', 'msime'
prop = $hinshi_t[type][prop]
r = sprintf "%s\t%s\t%s", pron, word, prop
when 'apple'
Download
End