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