Update copyright year to 2014 by running admin/update-copyright.
[bpt/emacs.git] / lisp / international / ja-dic-cnv.el
CommitLineData
60370d40 1;;; ja-dic-cnv.el --- convert a Japanese dictionary (SKK-JISYO.L) to Emacs Lisp
b47a7926 2
ba318903 3;; Copyright (C) 2001-2014 Free Software Foundation, Inc.
cb6c95a3 4
7976eda0 5;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5df4f04c 6;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
2fd125a3
KH
7;; National Institute of Advanced Industrial Science and Technology (AIST)
8;; Registration Number H14PRO021
b47a7926 9
49e64228 10;; Keywords: i18n, mule, multilingual, Japanese
b47a7926
KH
11
12;; This file is part of GNU Emacs.
13
4936186e 14;; GNU Emacs is free software: you can redistribute it and/or modify
b47a7926 15;; it under the terms of the GNU General Public License as published by
4936186e
GM
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
b47a7926
KH
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
4936186e 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
b47a7926
KH
26
27;;; Commentary:
28
29;; SKK is a Japanese input method running on Mule created by Masahiko
30;; Sato <masahiko@sato.riec.tohoku.ac.jp>. Here we provide utilities
31;; to handle a dictionary distributed with SKK so that a different
32;; input method (e.g. quail-japanese) can utilize the dictionary.
33
34;; The format of SKK dictionary is quite simple. Each line has the
35;; form "KANASTRING /CONV1/CONV2/.../" which means KANASTRING (\e$B2>L>J8\e(B
36;; \e$B;zNs\e(B) can be converted to one of CONVi. CONVi is a Kanji (\e$B4A;z\e(B)
37;; and Kana (\e$B2>L>\e(B) mixed string.
38;;
39;; KANASTRING may have a trailing ASCII letter for Okurigana (\e$BAw$j2>L>\e(B)
40;; information. For instance, the trailing letter `k' means that one
41;; of the following Okurigana is allowed: \e$B$+$-$/$1$3\e(B. So, in that
42;; case, the string "KANASTRING\e$B$/\e(B" can be converted to one of "CONV1\e$B$/\e(B",
43;; CONV2\e$B$/\e(B, ...
44
45;;; Code:
46
47;; Name of a file to generate from SKK dictionary.
48(defvar ja-dic-filename "ja-dic.el")
49
b47a7926
KH
50(defun skkdic-convert-okuri-ari (skkbuf buf)
51 (message "Processing OKURI-ARI entries ...")
52 (goto-char (point-min))
9a529312 53 (with-current-buffer buf
b47a7926
KH
54 (insert ";; Setting okuri-ari entries.\n"
55 "(skkdic-set-okuri-ari\n"))
56 (while (not (eobp))
fa6ea913
KH
57 (if (/= (following-char) ?>)
58 (let ((from (point))
59 (to (line-end-position)))
60 (with-current-buffer buf
61 (insert-buffer-substring skkbuf from to)
62 (beginning-of-line)
63 (insert "\"")
64 (search-forward " ")
65 (delete-char 1) ; delete the first '/'
66 (let ((p (point)))
67 (end-of-line)
68 (delete-char -1) ; delete the last '/'
69 (subst-char-in-region p (point) ?/ ? 'noundo))
70 (insert "\"\n"))))
71
72 (forward-line 1))
9a529312 73 (with-current-buffer buf
b47a7926
KH
74 (insert ")\n\n")))
75
76(defconst skkdic-postfix-list '(skkdic-postfix-list))
77
78(defconst skkdic-postfix-data
79 '(("\e$B$$$-\e(B" "\e$B9T\e(B")
80 ("\e$B$,$+$j\e(B" "\e$B78\e(B")
81 ("\e$B$,$/\e(B" "\e$B3X\e(B")
82 ("\e$B$,$o\e(B" "\e$B@n\e(B")
83 ("\e$B$7$c\e(B" "\e$B<R\e(B")
84 ("\e$B$7$e$&\e(B" "\e$B=8\e(B")
85 ("\e$B$7$g$&\e(B" "\e$B>^\e(B" "\e$B>k\e(B")
86 ("\e$B$8$g$&\e(B" "\e$B>k\e(B")
87 ("\e$B$;$s\e(B" "\e$B@~\e(B")
88 ("\e$B$@$1\e(B" "\e$B3Y\e(B")
89 ("\e$B$A$c$/\e(B" "\e$BCe\e(B")
90 ("\e$B$F$s\e(B" "\e$BE9\e(B")
91 ("\e$B$H$&$2\e(B" "\e$BF=\e(B")
92 ("\e$B$I$*$j\e(B" "\e$BDL$j\e(B")
93 ("\e$B$d$^\e(B" "\e$B;3\e(B")
94 ("\e$B$P$7\e(B" "\e$B66\e(B")
95 ("\e$B$O$D\e(B" "\e$BH/\e(B")
96 ("\e$B$b$/\e(B" "\e$BL\\e(B")
97 ("\e$B$f$-\e(B" "\e$B9T\e(B")))
98
99(defun skkdic-convert-postfix (skkbuf buf)
100 (message "Processing POSTFIX entries ...")
101 (goto-char (point-min))
9a529312 102 (with-current-buffer buf
b47a7926
KH
103 (insert ";; Setting postfix entries.\n"
104 "(skkdic-set-postfix\n"))
105
106 ;; Initialize SKKDIC-POSTFIX-LIST by predefined data
107 ;; SKKDIC-POSTFIX-DATA.
9a529312 108 (with-current-buffer buf
b47a7926
KH
109 (let ((l skkdic-postfix-data)
110 kana candidates entry)
111 (while l
112 (setq kana (car (car l)) candidates (cdr (car l)))
113 (insert "\"" kana)
114 (while candidates
115 (insert " " (car candidates))
116 (setq entry (lookup-nested-alist (car candidates)
117 skkdic-postfix-list nil nil t))
118 (if (consp (car entry))
119 (setcar entry (cons kana (car entry)))
120 (set-nested-alist (car candidates) (list kana)
121 skkdic-postfix-list))
122 (setq candidates (cdr candidates)))
123 (insert "\"\n")
124 (setq l (cdr l)))))
125
126 ;; Search postfix entries.
127 (while (re-search-forward "^[#<>?]\\(\\(\\cH\\|\e$B!<\e(B\\)+\\) " nil t)
128 (let ((kana (match-string 1))
129 str candidates)
130 (while (looking-at "/[#0-9 ]*\\([^/\n]*\\)/")
131 (setq str (match-string 1))
132 (if (not (member str candidates))
133 (setq candidates (cons str candidates)))
134 (goto-char (match-end 1)))
9a529312 135 (with-current-buffer buf
b47a7926
KH
136 (insert "\"" kana)
137 (while candidates
138 (insert " " (car candidates))
139 (let ((entry (lookup-nested-alist (car candidates)
140 skkdic-postfix-list nil nil t)))
141 (if (consp (car entry))
142 (if (not (member kana (car entry)))
143 (setcar entry (cons kana (car entry))))
144 (set-nested-alist (car candidates) (list kana)
145 skkdic-postfix-list)))
146 (setq candidates (cdr candidates)))
147 (insert "\"\n"))))
9a529312 148 (with-current-buffer buf
b47a7926 149 (insert ")\n\n")))
a1506d29 150
b47a7926
KH
151(defconst skkdic-prefix-list '(skkdic-prefix-list))
152
153(defun skkdic-convert-prefix (skkbuf buf)
154 (message "Processing PREFIX entries ...")
155 (goto-char (point-min))
9a529312 156 (with-current-buffer buf
b47a7926
KH
157 (insert ";; Setting prefix entries.\n"
158 "(skkdic-set-prefix\n"))
159 (save-excursion
160 (while (re-search-forward "^\\(\\(\\cH\\|\e$B!<\e(B\\)+\\)[<>?] " nil t)
161 (let ((kana (match-string 1))
162 str candidates)
163 (while (looking-at "/\\([^/\n]+\\)/")
164 (setq str (match-string 1))
165 (if (not (member str candidates))
166 (setq candidates (cons str candidates)))
167 (goto-char (match-end 1)))
9a529312 168 (with-current-buffer buf
b47a7926
KH
169 (insert "\"" kana)
170 (while candidates
171 (insert " " (car candidates))
172 (set-nested-alist (car candidates) kana skkdic-prefix-list)
173 (setq candidates (cdr candidates)))
174 (insert "\"\n")))))
9a529312 175 (with-current-buffer buf
b47a7926 176 (insert ")\n\n")))
a1506d29 177
b47a7926
KH
178;; FROM and TO point the head and tail of "/J../J../.../".
179(defun skkdic-get-candidate-list (from to)
180 (let (candidates)
181 (goto-char from)
38d777a8 182 (while (re-search-forward "/[^/ \n]+" to t)
b47a7926
KH
183 (setq candidates (cons (buffer-substring (1+ (match-beginning 0))
184 (match-end 0))
185 candidates)))
186 candidates))
187
188;; Return entry for STR from nested alist ALIST.
189(defsubst skkdic-get-entry (str alist)
190 (car (lookup-nested-alist str alist nil nil t)))
191
192
193(defconst skkdic-word-list '(skkdic-word-list))
194
195;; Return t if substring of STR (between FROM and TO) can be broken up
196;; to chunks all of which can be derived from another entry in SKK
197;; dictionary. SKKBUF is the buffer where the original SKK dictionary
3ecd3a56
GM
198;; is visited, KANA is the current entry for STR. FIRST is t only if
199;; this is called at top level.
b47a7926
KH
200
201(defun skkdic-breakup-string (skkbuf kana str from to &optional first)
202 (let ((len (- to from)))
203 (or (and (>= len 2)
204 (let ((min-idx (+ from 2))
205 (idx (if first (1- to ) to))
206 (found nil))
207 (while (and (not found) (>= idx min-idx))
208 (let ((kana2-list (skkdic-get-entry
209 (substring str from idx)
210 skkdic-word-list)))
211 (if (or (and (consp kana2-list)
212 (let ((kana-len (length kana))
213 kana2)
214 (catch 'skkdic-tag
215 (while kana2-list
216 (setq kana2 (car kana2-list))
217 (if (string-match kana2 kana)
218 (throw 'skkdic-tag t))
219 (setq kana2-list (cdr kana2-list)))))
220 (or (= idx to)
221 (skkdic-breakup-string skkbuf kana str
222 idx to)))
223 (and (stringp kana2-list)
224 (string-match kana2-list kana)))
225 (setq found t)
226 (setq idx (1- idx)))))
227 found))
228 (and first
229 (> len 2)
230 (let ((kana2 (skkdic-get-entry
231 (substring str from (1+ from))
232 skkdic-prefix-list)))
233 (and (stringp kana2)
234 (eq (string-match kana2 kana) 0)))
235 (skkdic-breakup-string skkbuf kana str (1+ from) to))
236 (and (not first)
237 (>= len 1)
238 (let ((kana2-list (skkdic-get-entry
239 (substring str from to)
240 skkdic-postfix-list)))
241 (and (consp kana2-list)
242 (let (kana2)
243 (catch 'skkdic-tag
244 (while kana2-list
245 (setq kana2 (car kana2-list))
246 (if (string= kana2
247 (substring kana (- (length kana2))))
248 (throw 'skkdic-tag t))
249 (setq kana2-list (cdr kana2-list)))))))))))
250
251;; Return list of candidates which excludes some from CANDIDATES.
252;; Excluded candidates can be derived from another entry.
253
254(defun skkdic-reduced-candidates (skkbuf kana candidates)
255 (let (elt l)
256 (while candidates
257 (setq elt (car candidates))
258 (if (or (= (length elt) 1)
259 (and (string-match "^\\cj" elt)
260 (not (skkdic-breakup-string skkbuf kana elt 0 (length elt)
261 'first))))
262 (setq l (cons elt l)))
263 (setq candidates (cdr candidates)))
264 (nreverse l)))
265
bb2ed48e
JPW
266(defvar skkdic-okuri-nasi-entries (list nil))
267(defvar skkdic-okuri-nasi-entries-count 0)
b47a7926
KH
268
269(defun skkdic-collect-okuri-nasi ()
270 (message "Collecting OKURI-NASI entries ...")
271 (save-excursion
272 (let ((prev-ratio 0)
273 ratio)
274 (while (re-search-forward "^\\(\\(\\cH\\|\e$B!<\e(B\\)+\\) \\(/\\cj.*\\)/$"
275 nil t)
276 (let ((kana (match-string 1))
277 (candidates (skkdic-get-candidate-list (match-beginning 3)
278 (match-end 3))))
279 (setq skkdic-okuri-nasi-entries
280 (cons (cons kana candidates) skkdic-okuri-nasi-entries)
281 skkdic-okuri-nasi-entries-count
282 (1+ skkdic-okuri-nasi-entries-count))
283 (setq ratio (floor (/ (* (point) 100.0) (point-max))))
2667d15d 284 (if (/= (/ prev-ratio 10) (/ ratio 10))
b47a7926 285 (progn
2667d15d 286 (message "collected %2d%% ..." ratio)
b47a7926
KH
287 (setq prev-ratio ratio)))
288 (while candidates
289 (let ((entry (lookup-nested-alist (car candidates)
290 skkdic-word-list nil nil t)))
291 (if (consp (car entry))
292 (setcar entry (cons kana (car entry)))
293 (set-nested-alist (car candidates) (list kana)
294 skkdic-word-list)))
295 (setq candidates (cdr candidates))))))))
296
297(defun skkdic-convert-okuri-nasi (skkbuf buf)
298 (message "Processing OKURI-NASI entries ...")
9a529312 299 (with-current-buffer buf
b47a7926
KH
300 (insert ";; Setting okuri-nasi entries.\n"
301 "(skkdic-set-okuri-nasi\n")
302 (let ((l (nreverse skkdic-okuri-nasi-entries))
303 (count 0)
304 (prev-ratio 0)
305 ratio)
306 (while l
307 (let ((kana (car (car l)))
308 (candidates (cdr (car l))))
2667d15d 309 (setq ratio (/ (* count 100) skkdic-okuri-nasi-entries-count)
b47a7926 310 count (1+ count))
2667d15d 311 (if (/= (/ prev-ratio 10) (/ ratio 10))
b47a7926 312 (progn
2667d15d
PE
313 (message "processed %2d%% ..." ratio)
314 (setq prev-ratio ratio)))
b47a7926
KH
315 (if (setq candidates
316 (skkdic-reduced-candidates skkbuf kana candidates))
317 (progn
318 (insert "\"" kana)
319 (while candidates
320 (insert " " (car candidates))
321 (setq candidates (cdr candidates)))
322 (insert "\"\n"))))
323 (setq l (cdr l))))
324 (insert ")\n\n")))
325
326(defun skkdic-convert (filename &optional dirname)
32ef9469 327 "Generate Emacs Lisp file form Japanese dictionary file FILENAME.
b47a7926
KH
328The format of the dictionary file should be the same as SKK dictionaries.
329Optional argument DIRNAME if specified is the directory name under which
330the generated Emacs Lisp is saved.
331The name of generated file is specified by the variable `ja-dic-filename'."
332 (interactive "FSKK dictionary file: ")
333 (message "Reading file \"%s\" ..." filename)
334 (let* ((coding-system-for-read 'euc-japan)
bad98418 335 (skkbuf (get-buffer-create " *skkdic-unannotated*"))
b47a7926 336 (buf (get-buffer-create "*skkdic-work*")))
982efbcd
PE
337 ;; Set skkbuf to an unannotated copy of the dictionary.
338 (with-current-buffer skkbuf
339 (insert-file-contents (expand-file-name filename))
340 (re-search-forward "^[^;]")
341 (while (re-search-forward ";[^\n/]*/" nil t)
342 (replace-match "/")))
9a529312
SM
343 ;; Setup and generate the header part of working buffer.
344 (with-current-buffer buf
b47a7926
KH
345 (erase-buffer)
346 (buffer-disable-undo)
cb6c95a3 347 (insert ";;; ja-dic.el --- dictionary for Japanese input method\n"
b47a7926 348 ";;\tGenerated by the command `skkdic-convert'\n"
b47a7926 349 ";;\tOriginal SKK dictionary file: "
091fee44 350 (file-relative-name (expand-file-name filename) dirname)
b47a7926 351 "\n\n"
381194d0 352 ";; This file is part of GNU Emacs.\n\n"
b47a7926
KH
353 ";;; Start of the header of the original SKK dictionary.\n\n")
354 (set-buffer skkbuf)
b47a7926
KH
355 (goto-char 1)
356 (let (pos)
357 (search-forward ";; okuri-ari")
358 (forward-line 1)
359 (setq pos (point))
360 (set-buffer buf)
361 (insert-buffer-substring skkbuf 1 pos))
362 (insert "\n"
c9ef1229 363 ";;; Code:\n\n(eval-when-compile (require 'ja-dic-cnv))\n\n")
b47a7926
KH
364
365 ;; Generate the body part of working buffer.
366 (set-buffer skkbuf)
367 (let ((from (point))
368 to)
369 ;; Convert okuri-ari entries.
370 (search-forward ";; okuri-nasi")
371 (beginning-of-line)
372 (setq to (point))
373 (narrow-to-region from to)
374 (skkdic-convert-okuri-ari skkbuf buf)
375 (widen)
376
377 ;; Convert okuri-nasi postfix entries.
378 (goto-char to)
379 (forward-line 1)
380 (setq from (point))
381 (re-search-forward "^\\cH")
382 (setq to (match-beginning 0))
383 (narrow-to-region from to)
384 (skkdic-convert-postfix skkbuf buf)
385 (widen)
386
387 ;; Convert okuri-nasi prefix entries.
388 (goto-char to)
389 (skkdic-convert-prefix skkbuf buf)
390
a1506d29 391 ;;
b47a7926
KH
392 (skkdic-collect-okuri-nasi)
393
394 ;; Convert okuri-nasi general entries.
395 (skkdic-convert-okuri-nasi skkbuf buf)
396
397 ;; Postfix
9a529312 398 (with-current-buffer buf
b47a7926 399 (goto-char (point-max))
cb6c95a3
GM
400 (insert ";;\n(provide 'ja-dic)\n\n"
401 ";; Local Variables:\n"
402 ";; version-control: never\n"
403 ";; no-update-autoloads: t\n"
404 ";; coding: utf-8\n"
405 ";; End:\n\n"
406 ";;; ja-dic.el ends here\n")))
b47a7926
KH
407
408 ;; Save the working buffer.
409 (set-buffer buf)
410 (set-visited-file-name (expand-file-name ja-dic-filename dirname) t)
982efbcd 411 (set-buffer-file-coding-system 'utf-8)
b47a7926
KH
412 (save-buffer 0))
413 (kill-buffer skkbuf)
414 (switch-to-buffer buf)))
415
416(defun batch-skkdic-convert ()
417 "Run `skkdic-convert' on the files remaining on the command line.
418Use this from the command line, with `-batch';
419it won't work in an interactive Emacs.
420For example, invoke:
421 % emacs -batch -l ja-dic-cnv -f batch-skkdic-convert SKK-JISYO.L
422to generate \"ja-dic.el\" from SKK dictionary file \"SKK-JISYO.L\".
423To get complete usage, invoke:
424 % emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -h"
425 (defvar command-line-args-left) ; Avoid compiler warning.
426 (if (not noninteractive)
427 (error "`batch-skkdic-convert' should be used only with -batch"))
428 (if (string= (car command-line-args-left) "-h")
429 (progn
430 (message "To convert SKK-JISYO.L into skkdic.el:")
431 (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert SKK-JISYO.L")
432 (message "To convert SKK-JISYO.L into DIR/ja-dic.el:")
433 (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -dir DIR SKK-JISYO.L"))
434 (let (targetdir filename)
435 (if (string= (car command-line-args-left) "-dir")
436 (progn
437 (setq command-line-args-left (cdr command-line-args-left))
438 (setq targetdir (expand-file-name (car command-line-args-left)))
439 (setq command-line-args-left (cdr command-line-args-left))))
440 (setq filename (expand-file-name (car command-line-args-left)))
2667d15d 441 (skkdic-convert filename targetdir)))
b47a7926
KH
442 (kill-emacs 0))
443
444
445;; The following macros are expanded at byte-compiling time so that
446;; compiled code can be loaded quickly.
447
448(defun skkdic-get-kana-compact-codes (kana)
449 (let* ((len (length kana))
450 (vec (make-vector len 0))
451 (i 0)
452 ch)
453 (while (< i len)
454 (setq ch (aref kana i))
455 (aset vec i
456 (if (< ch 128) ; CH is an ASCII letter for OKURIGANA,
457 (- ch) ; represented by a negative code.
458 (if (= ch ?\e$B!<\e(B) ; `\e$B!<\e(B' is represented by 0.
459 0
a10201c8 460 (- (logand (encode-char ch 'japanese-jisx0208) #xFF) 32))))
b47a7926
KH
461 (setq i (1+ i)))
462 vec))
463
464(defun skkdic-extract-conversion-data (entry)
465 (string-match "^\\cj+[a-z]* " entry)
466 (let ((kana (substring entry (match-beginning 0) (1- (match-end 0))))
467 (i (match-end 0))
468 candidates)
469 (while (string-match "[^ ]+" entry i)
470 (setq candidates (cons (match-string 0 entry) candidates))
471 (setq i (match-end 0)))
472 (cons (skkdic-get-kana-compact-codes kana) candidates)))
473
474(defmacro skkdic-set-okuri-ari (&rest entries)
475 `(defconst skkdic-okuri-ari
476 ',(let ((l entries)
477 (map '(skkdic-okuri-ari))
478 entry)
479 (while l
480 (setq entry (skkdic-extract-conversion-data (car l)))
481 (set-nested-alist (car entry) (cdr entry) map)
482 (setq l (cdr l)))
483 map)))
484
485(defmacro skkdic-set-postfix (&rest entries)
486 `(defconst skkdic-postfix
487 ',(let ((l entries)
488 (map '(nil))
489 (longest 1)
490 len entry)
491 (while l
492 (setq entry (skkdic-extract-conversion-data (car l)))
493 (setq len (length (car entry)))
494 (if (> len longest)
495 (setq longest len))
496 (let ((entry2 (lookup-nested-alist (car entry) map nil nil t)))
497 (if (consp (car entry2))
498 (let ((conversions (cdr entry)))
499 (while conversions
500 (if (not (member (car conversions) (car entry2)))
501 (setcar entry2 (cons (car conversions) (car entry2))))
502 (setq conversions (cdr conversions))))
503 (set-nested-alist (car entry) (cdr entry) map)))
504 (setq l (cdr l)))
505 (setcar map longest)
506 map)))
507
508(defmacro skkdic-set-prefix (&rest entries)
509 `(defconst skkdic-prefix
510 ',(let ((l entries)
511 (map '(nil))
512 (longest 1)
513 len entry)
514 (while l
515 (setq entry (skkdic-extract-conversion-data (car l)))
516 (setq len (length (car entry)))
517 (if (> len longest)
518 (setq longest len))
519 (let ((entry2 (lookup-nested-alist (car entry) map len nil t)))
520 (if (consp (car entry2))
521 (let ((conversions (cdr entry)))
522 (while conversions
523 (if (not (member (car conversions) (car entry2)))
524 (setcar entry2 (cons (car conversions) (car entry2))))
525 (setq conversions (cdr conversions))))
526 (set-nested-alist (car entry) (cdr entry) map len)))
527 (setq l (cdr l)))
528 (setcar map longest)
529 map)))
530
531(defmacro skkdic-set-okuri-nasi (&rest entries)
532 `(defconst skkdic-okuri-nasi
533 ',(let ((l entries)
534 (map '(skdic-okuri-nasi))
535 (count 0)
536 entry)
537 (while l
538 (setq count (1+ count))
50e3a346 539 (if (= (% count 10000) 0)
274f1353 540 (message "%d entries" count))
b47a7926
KH
541 (setq entry (skkdic-extract-conversion-data (car l)))
542 (set-nested-alist (car entry) (cdr entry) map)
543 (setq l (cdr l)))
544 map)))
545
546(provide 'ja-dic-cnv)
547
5bbba7b2
KH
548;; Local Variables:
549;; coding: iso-2022-7bit
550;; End:
60370d40
PJ
551
552;;; ja-dic-cnv.el ends here