* ew-dec.el (ew-decode-field-test): Change column.
[elisp/flim.git] / mel-ccl.el
1 (require 'ccl)
2 (require 'emu)
3
4
5 ;;; @ constants
6 ;;;
7
8 (eval-when-compile
9
10 (defconst mel-ccl-4-table
11   '(  0   1   2   3))
12
13 (defconst mel-ccl-16-table
14   '(  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15))
15
16 (defconst mel-ccl-64-table
17   '(  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
18      16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
19      32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47
20      48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63))
21
22 (defconst mel-ccl-256-table
23   '(  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
24      16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
25      32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47
26      48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63
27      64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79
28      80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95
29      96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111
30     112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
31     128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
32     144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
33     160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
34     176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
35     192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
36     208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
37     224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
38     240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255))
39
40 (defconst mel-ccl-256-to-16-table
41   '(nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
42     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
43     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
44       0   1   2   3   4   5   6   7   8   9 nil nil nil nil nil nil
45     nil  10  11  12  13  14  15 nil nil nil nil nil nil nil nil nil
46     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
47     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
48     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
49     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
50     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
51     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
52     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
53     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
54     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
55     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
56     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil))
57
58 (defconst mel-ccl-16-to-256-table
59   '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?A ?B ?C ?D ?E ?F))
60
61 (defconst mel-ccl-high-table
62   (vconcat
63    (mapcar
64     (lambda (v) (nth (lsh v -4) mel-ccl-16-to-256-table))
65     mel-ccl-256-table)))
66
67 (defconst mel-ccl-low-table
68   (vconcat
69    (mapcar
70     (lambda (v) (nth (logand v 15) mel-ccl-16-to-256-table))
71     mel-ccl-256-table)))
72
73 (defconst mel-ccl-u-raw
74   (append
75    "0123456789"
76    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
77    "abcdefghijklmnopqrstuvwxyz"
78    "!@#$%&'()*+,-./:;<>@[\\]^`{|}~"
79    ()))
80
81 (defconst mel-ccl-c-raw
82   (append
83    "0123456789"
84    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
85    "abcdefghijklmnopqrstuvwxyz"
86    "!@#$%&'*+,-./:;<>@[]^`{|}~"
87    ()))
88
89 (defconst mel-ccl-p-raw
90   (append
91    "0123456789"
92    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
93    "abcdefghijklmnopqrstuvwxyz"
94    "!*+-/"
95    ()))
96
97 (defconst mel-ccl-256-to-64-table
98   '(nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
99     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
100     nil nil nil nil nil nil nil nil nil nil nil  62 nil nil nil  63
101      52  53  54  55  56  57  58  59  60  61 nil nil nil   t nil nil
102     nil   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14
103      15  16  17  18  19  20  21  22  23  24  25 nil nil nil nil nil
104     nil  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40
105      41  42  43  44  45  46  47  48  49  50  51 nil nil nil nil nil
106     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
107     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
108     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
109     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
110     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
111     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
112     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
113     nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil))
114
115 (defconst mel-ccl-64-to-256-table
116   '(?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P
117     ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z ?a ?b ?c ?d ?e ?f
118     ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v
119     ?w ?x ?y ?z ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?+ ?/))
120
121 (defconst mel-ccl-qp-table
122   [enc enc enc enc enc enc enc enc enc wsp enc enc enc cr  enc enc
123    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
124    wsp raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw
125    raw raw raw raw raw raw raw raw raw raw raw raw raw enc raw raw
126    raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw
127    raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw
128    raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw
129    raw raw raw raw raw raw raw raw raw raw raw raw raw raw raw enc
130    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
131    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
132    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
133    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
134    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
135    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
136    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc
137    enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc enc])
138
139 )
140
141
142 ;;; @ CCL programs
143 ;;;
144
145 (define-ccl-program mel-ccl-decode-q
146   `(1
147     ((loop
148       (read-branch
149        r0
150        ,@(mapcar
151           (lambda (r0)
152             (cond
153              ((= r0 ?_)
154               `(write-repeat ? ))
155              ((= r0 ?=)
156               `((loop
157                  (read-branch
158                   r1
159                   ,@(mapcar
160                      (lambda (v)
161                        (if (integerp v)
162                            `((r0 = ,v) (break))
163                          '(repeat)))
164                      mel-ccl-256-to-16-table)))
165                 (loop
166                  (read-branch
167                   r1
168                   ,@(mapcar
169                      (lambda (v)
170                        (if (integerp v)
171                            `((write r0 ,(vconcat
172                                          (mapcar
173                                           (lambda (r0)
174                                             (logior (lsh r0 4) v))
175                                           mel-ccl-16-table)))
176                              (break))
177                          '(repeat)))
178                      mel-ccl-256-to-16-table)))
179                 (repeat)))
180              (t
181               `(write-repeat ,r0))))
182           mel-ccl-256-table))))))
183
184 (define-ccl-program mel-ccl-encode-uq
185   `(3
186     (loop
187      (loop
188       (read-branch
189        r0
190        ,@(mapcar
191           (lambda (r0)
192             (cond
193              ((= r0 32) `(write-repeat ?_))
194              ((member r0 mel-ccl-u-raw) `(write-repeat ,r0))
195              (t '(break))))
196           mel-ccl-256-table)))
197      (write ?=)
198      (write r0 ,mel-ccl-high-table)
199      (write r0 ,mel-ccl-low-table)
200      (repeat))))
201
202 (define-ccl-program mel-ccl-encode-cq
203   `(3
204     (loop
205      (loop
206       (read-branch
207        r0
208        ,@(mapcar
209           (lambda (r0)
210             (cond
211              ((= r0 32) `(write-repeat ?_))
212              ((member r0 mel-ccl-c-raw) `(write-repeat ,r0))
213              (t '(break))))
214           mel-ccl-256-table)))
215      (write ?=)
216      (write r0 ,mel-ccl-high-table)
217      (write r0 ,mel-ccl-low-table)
218      (repeat))))
219
220 (define-ccl-program mel-ccl-encode-pq
221   `(3
222     (loop
223      (loop
224       (read-branch
225        r0
226        ,@(mapcar
227           (lambda (r0)
228             (cond
229              ((= r0 32) `(write-repeat ?_))
230              ((member r0 mel-ccl-p-raw) `(write-repeat ,r0))
231              (t '(break))))
232           mel-ccl-256-table)))
233      (write ?=)
234      (write r0 ,mel-ccl-high-table)
235      (write r0 ,mel-ccl-low-table)
236      (repeat))))
237
238 (eval-when-compile
239 (defun mel-ccl-decode-b-bit-ex (v)
240   (logior
241    (lsh (logand v (lsh 255 16)) -16)
242    (logand v (lsh 255 8))
243    (lsh (logand v 255) 16)))
244
245 (defconst mel-ccl-decode-b-0-table
246   (vconcat
247    (mapcar
248     (lambda (v)
249       (if (integerp v)
250           (mel-ccl-decode-b-bit-ex (lsh v 18))
251         (lsh 1 24)))
252     mel-ccl-256-to-64-table)))
253
254 (defconst mel-ccl-decode-b-1-table
255   (vconcat
256    (mapcar
257     (lambda (v)
258       (if (integerp v)
259           (mel-ccl-decode-b-bit-ex (lsh v 12))
260         (lsh 1 25)))
261     mel-ccl-256-to-64-table)))
262
263 (defconst mel-ccl-decode-b-2-table
264   (vconcat
265    (mapcar
266     (lambda (v)
267       (if (integerp v)
268           (mel-ccl-decode-b-bit-ex (lsh v 6))
269         (lsh 1 26)))
270     mel-ccl-256-to-64-table)))
271
272 (defconst mel-ccl-decode-b-3-table
273   (vconcat
274    (mapcar
275     (lambda (v)
276       (if (integerp v)
277           (mel-ccl-decode-b-bit-ex v)
278         (lsh 1 27)))
279     mel-ccl-256-to-64-table)))
280
281 )
282
283 (define-ccl-program mel-ccl-decode-b
284   `(1
285     (loop
286      (read r0 r1 r2 r3)
287      (r4 = r0 ,mel-ccl-decode-b-0-table)
288      (r5 = r1 ,mel-ccl-decode-b-1-table)
289      (r4 |= r5)
290      (r5 = r2 ,mel-ccl-decode-b-2-table)
291      (r4 |= r5)
292      (r5 = r3 ,mel-ccl-decode-b-3-table)
293      (r4 |= r5)
294      (if (r4 & ,(lognot (1- (lsh 1 24))))
295          ((loop
296            (if (r4 & ,(lsh 1 24))
297                ((r0 = r1) (r1 = r2) (r2 = r3) (read r3)
298                 (r4 >>= 1) (r4 &= ,(logior (lsh 7 24)))
299                 (r5 = r3 ,mel-ccl-decode-b-3-table)
300                 (r4 |= r5)
301                 (repeat))
302              (break)))
303           (loop
304            (if (r4 & ,(lsh 1 25))
305                ((r1 = r2) (r2 = r3) (read r3)
306                 (r4 >>= 1) (r4 &= ,(logior (lsh 7 24)))
307                 (r5 = r3 ,mel-ccl-decode-b-3-table)
308                 (r4 |= r5)
309                 (repeat))
310              (break)))
311           (loop
312            (if (r2 != ?=)
313                (if (r4 & ,(lsh 1 26))
314                    ((r2 = r3) (read r3)
315                     (r4 >>= 1) (r4 &= ,(logior (lsh 7 24)))
316                     (r5 = r3 ,mel-ccl-decode-b-3-table)
317                     (r4 |= r5)
318                     (repeat))
319                  ((r6 = 0)
320                   (break)))
321              ((r6 = 1)
322               (break))))
323           (loop
324            (if (r3 != ?=)
325                (if (r4 & ,(lsh 1 27))
326                    ((read r3)
327                     (r4 = r3 ,mel-ccl-decode-b-3-table)
328                     (repeat))
329                  (break))
330              ((r6 |= 2)
331               (break))))
332           (r4 = r0 ,mel-ccl-decode-b-0-table)
333           (r5 = r1 ,mel-ccl-decode-b-1-table)
334           (r4 |= r5)
335           (branch
336            r6
337            ;; BBBB
338            ((r5 = r2 ,mel-ccl-decode-b-2-table)
339             (r4 |= r5)
340             (r5 = r3 ,mel-ccl-decode-b-3-table)
341             (r4 |= r5)
342             (r4 >8= 0)
343             (write r7)
344             (r4 >8= 0)
345             (write r7)
346             (write-repeat r4))
347            ;; error: BB=B 
348            ((write r4)
349             (end))
350            ;; BBB=
351            ((r5 = r2 ,mel-ccl-decode-b-2-table)
352             (r4 |= r5)
353             (r4 >8= 0)
354             (write r7)
355             (write r4)
356             (end))
357            ;; BB==
358            ((write r4)
359             (end))))
360        ((r4 >8= 0)
361         (write r7)
362         (r4 >8= 0)
363         (write r7)
364         (write-repeat r4))))))
365
366 ;; mel-ccl-encode-b works only 20.3 or later because CCL_EOF_BLOCK
367 ;; is not executed on 20.2 (or former?).
368 (define-ccl-program mel-ccl-encode-b
369   `(2
370     (loop
371      (r2 = 0)
372      (read-branch
373       r1
374       ,@(mapcar
375          (lambda (r1)
376            `((write ,(nth (lsh r1 -2) mel-ccl-64-to-256-table))
377              (r0 = ,(logand r1 3))))
378          mel-ccl-256-table))
379      (r2 = 1)
380      (read-branch
381       r1
382       ,@(mapcar
383          (lambda (r1)
384            `((write r0 ,(vconcat
385                          (mapcar
386                           (lambda (r0)
387                             (nth (logior (lsh r0 4)
388                                          (lsh r1 -4))
389                                  mel-ccl-64-to-256-table))
390                           mel-ccl-4-table)))
391              (r0 = ,(logand r1 15))))
392          mel-ccl-256-table))
393      (r2 = 2)
394      (read-branch
395       r1
396       ,@(mapcar
397          (lambda (r1)
398            `((write r0 ,(vconcat
399                          (mapcar
400                           (lambda (r0)
401                             (nth (logior (lsh r0 2)
402                                          (lsh r1 -6))
403                                  mel-ccl-64-to-256-table))
404                           mel-ccl-16-table)))))
405          mel-ccl-256-table))
406      (r1 &= 63)
407      (write r1 ,(vconcat
408                  (mapcar
409                   (lambda (r1)
410                     (nth r1 mel-ccl-64-to-256-table))
411                   mel-ccl-64-table)))
412      (repeat))
413     (branch
414      r2
415      (end)
416      ((write r0 ,(vconcat
417                   (mapcar
418                    (lambda (r0)
419                      (nth (lsh r0 4) mel-ccl-64-to-256-table))
420                    mel-ccl-4-table)))
421       (write "=="))
422      ((write r0 ,(vconcat
423                   (mapcar
424                    (lambda (r0)
425                      (nth (lsh r0 2) mel-ccl-64-to-256-table))
426                    mel-ccl-16-table)))
427       (write ?=)))
428     ))
429
430 ;; mel-ccl-encode-base64 does not works on 20.2 by same reason of mel-ccl-encode-b
431 (define-ccl-program mel-ccl-encode-base64
432   `(2
433     ((r3 = 0)
434      (loop
435       (r2 = 0)
436       (read-branch
437        r1
438        ,@(mapcar
439           (lambda (r1)
440             `((write ,(nth (lsh r1 -2) mel-ccl-64-to-256-table))
441               (r0 = ,(logand r1 3))))
442           mel-ccl-256-table))
443       (r2 = 1)
444       (read-branch
445        r1
446        ,@(mapcar
447           (lambda (r1)
448             `((write r0 ,(vconcat
449                           (mapcar
450                            (lambda (r0)
451                              (nth (logior (lsh r0 4)
452                                           (lsh r1 -4))
453                                   mel-ccl-64-to-256-table))
454                            mel-ccl-4-table)))
455               (r0 = ,(logand r1 15))))
456           mel-ccl-256-table))
457       (r2 = 2)
458       (read-branch
459        r1
460        ,@(mapcar
461           (lambda (r1)
462             `((write r0 ,(vconcat
463                           (mapcar
464                            (lambda (r0)
465                              (nth (logior (lsh r0 2)
466                                           (lsh r1 -6))
467                                   mel-ccl-64-to-256-table))
468                            mel-ccl-16-table)))))
469           mel-ccl-256-table))
470       (r1 &= 63)
471       (write r1 ,(vconcat
472                   (mapcar
473                    (lambda (r1)
474                      (nth r1 mel-ccl-64-to-256-table))
475                    mel-ccl-64-table)))
476       (r3 += 1)
477       (if (r3 == 19) ; 4 * 19 = 76 --> line break.
478           ((write "\r\n")
479            (r3 = 0)))
480       (repeat)))
481     (branch
482      r2
483      (if (r0 > 0) (write "\r\n"))
484      ((write r0 ,(vconcat
485                   (mapcar
486                    (lambda (r0)
487                      (nth (lsh r0 4) mel-ccl-64-to-256-table))
488                    mel-ccl-4-table)))
489       (write "==\r\n"))
490      ((write r0 ,(vconcat
491                   (mapcar
492                    (lambda (r0)
493                      (nth (lsh r0 2) mel-ccl-64-to-256-table))
494                    mel-ccl-16-table)))
495       (write "=\r\n")))
496     ))
497
498 ;; mel-ccl-encode-quoted-printable does not works on 20.2 by same reason of mel-ccl-encode-b
499 (define-ccl-program mel-ccl-encode-quoted-printable
500   `(4
501     ((r6 = 0) ; column
502      (r5 = 0) ; previous character is white space
503      (r4 = 0)
504      (read r0)
505      (loop ; r6 <= 75
506       (loop
507        (loop
508         (branch
509          r0
510          ,@(mapcar
511             (lambda (r0)
512               (let ((tmp (aref mel-ccl-qp-table r0)))
513                 (cond
514                  ((eq tmp 'raw) '((r3 = 0) (break))) ; RAW
515                  ((eq tmp 'enc) '((r3 = 1) (break))) ; ENC
516                  ((eq tmp 'wsp) '((r3 = 2) (break))) ; WSP
517                  ((eq tmp 'cr) '((r3 = 3) (break))) ; CR
518                  )))
519             mel-ccl-256-table)))
520        (branch
521         r3
522         ;; r0:r3=RAW
523         (if (r6 < 75)
524             ((r6 += 1)
525              (r5 = 0)
526              (r4 = 1)
527              (write-read-repeat r0))
528           (break))
529         ;; r0:r3=ENC
530         ((r5 = 0)
531          (if (r6 < 73)
532              ((r6 += 3)
533               (write "=")
534               (write r0 ,mel-ccl-high-table)
535               (r4 = 2)
536               (write-read-repeat r0 ,mel-ccl-low-table))
537            (if (r6 > 73)
538                ((r6 = 3)
539                 (write "=\r\n=")
540                 (write r0 ,mel-ccl-high-table)
541                 (r4 = 3)
542                 (write-read-repeat r0 ,mel-ccl-low-table))
543              (break))))
544         ;; r0:r3=WSP
545         ((r5 = 1)
546          (if (r6 < 75)
547              ((r6 += 1)
548               (r4 = 4)
549               (write-read-repeat r0))
550            ((r6 = 1)
551             (write "=\r\n")
552             (r4 = 5)
553             (write-read-repeat r0))))
554         ;; r0:r3=CR
555         ((if ((r6 > 73) & r5)
556              ((r6 = 0)
557               (r5 = 0)
558               (write "=\r\n")))
559          (break))))
560       ;; r0:r3={RAW,ENC,CR}
561       (loop
562        (if (r0 == ?\r)
563            ;; r0=\r:r3=CR
564            ((r4 = 6)
565             (read r0)
566             ;; CR:r3=CR r0
567             (if (r0 == ?\n)
568                 ;; CR:r3=CR r0=LF
569                 (if r5
570                     ;; r5=WSP ; CR:r3=CR r0=LF
571                     ((r6 = 0)
572                      (r5 = 0)
573                      (write "=\r\n\r\n")
574                      (r4 = 7)
575                      (read r0)
576                      (break))
577                   ;; r5=noWSP ; CR:r3=CR r0=LF
578                   ((r6 = 0)
579                    (r5 = 0)
580                    (write "\r\n")
581                    (r4 = 8)
582                    (read r0)
583                    (break)))
584               ;; CR:r3=CR r0=noLF
585               (if (r6 < 73)
586                   ((r6 += 3)
587                    (r5 = 0)
588                    (write "=0D")
589                    (break))
590                 (if (r6 == 73)
591                     (if (r0 == ?\r)
592                         ;; CR:r3=CR r0=CR
593                         ((r4 = 9)
594                          (read r0)
595                          ;; CR:r3=CR CR r0
596                          (if (r0 == ?\n)
597                              ;; CR:r3=CR CR LF
598                              ((r6 = 0)
599                               (r5 = 0)
600                               (write "=0D\r\n")
601                               (r4 = 10)
602                               (read r0)
603                               (break))
604                            ;; CR:r3=CR CR noLF
605                            ((r6 = 6)
606                             (r5 = 0)
607                             (write "=\r\n=0D=0D")
608                             (break))))
609                       ;; CR:r3=CR r0=noLFnorCR
610                       ((r6 = 3)
611                        (r5 = 0)
612                        (write "=\r\n=0D")
613                        (break)))
614                   ((r6 = 3)
615                    (r5 = 0)
616                    (write "=\r\n=0D")
617                    (break))))))
618          ;; r0:r3={RAW,ENC}
619          ((r4 = 11)
620           (read r1)
621           ;; r0:r3={RAW,ENC} r1
622           (if (r1 == ?\r)
623               ;; r0:r3={RAW,ENC} r1=CR
624               ((r4 = 12)
625                (read r1)
626                ;; r0:r3={RAW,ENC} CR r1
627                (if (r1 == ?\n)
628                    ;; r0:r3={RAW,ENC} CR r1=LF
629                    ((r6 = 0)
630                     (r5 = 0)
631                     (branch
632                      r3
633                      ;; r0:r3=RAW CR r1=LF
634                      ((write r0)
635                       (write "\r\n")
636                       (r4 = 13)
637                       (read r0)
638                       (break))
639                      ;; r0:r3=ENC CR r1=LF
640                      ((write ?=)
641                       (write r0 ,mel-ccl-high-table)
642                       (write r0 ,mel-ccl-low-table)
643                       (write "\r\n")
644                       (r4 = 14)
645                       (read r0)
646                       (break))))
647                  ;; r0:r3={RAW,ENC} CR r1=noLF
648                  ((branch
649                    r3
650                    ;; r0:r3=RAW CR r1:noLF
651                    ((r6 = 4)
652                     (r5 = 0)
653                     (write "=\r\n")
654                     (write r0)
655                     (write "=0D")
656                     (r0 = r1)
657                     (break))
658                    ;; r0:r3=ENC CR r1:noLF
659                    ((r6 = 6)
660                     (r5 = 0)
661                     (write "=\r\n=")
662                     (write r0 ,mel-ccl-high-table)
663                     (write r0 ,mel-ccl-low-table)
664                     (write "=0D")
665                     (r0 = r1)
666                     (break))))
667                  ))
668             ;; r0:r3={RAW,ENC} r1:noCR
669             ((branch
670               r3
671               ;; r0:r3=RAW r1:noCR
672               ((r6 = 1)
673                (r5 = 0)
674                (write "=\r\n")
675                (write r0)
676                (r0 = r1)
677                (break))
678               ;; r0:r3=ENC r1:noCR
679               ((r6 = 3)
680                (r5 = 0)
681                (write "=\r\n=")
682                (write r0 ,mel-ccl-high-table)
683                (write r0 ,mel-ccl-low-table)
684                (r0 = r1)
685                (break))))))))
686       (repeat)))
687     (;(write "[EOF:") (write r4 ,mel-ccl-high-table) (write r4 ,mel-ccl-low-table) (write "]")
688      (branch
689       r4
690       ;; 0: (start) ;
691       (end)
692       ;; 1: RAW ;
693       (end)
694       ;; 2: r0:r3=ENC ;
695       (end)
696       ;; 3: SOFTBREAK r0:r3=ENC ;
697       (end)
698       ;; 4: r0:r3=WSP ;
699       ((write "=\r\n") (end))
700       ;; 5: SOFTBREAK r0:r3=WSP ;
701       ((write "=\r\n") (end))
702       ;; 6: ; r0=\r:r3=CR
703       (if (r6 <= 73)
704           ((write "=0D") (end))
705          ((write "=\r\n=0D") (end)))
706       ;; 7: r5=WSP SOFTBREAK CR:r3=CR r0=LF ;
707       (end)
708       ;; 8: r5=noWSP CR:r3=CR r0=LF ;
709       (end)
710       ;; 9: (r6=73) ; CR:r3=CR r0=CR
711       ((write "=\r\n=0D=0D") (end))
712       ;; 10: (r6=73) CR:r3=CR CR LF ;
713       (end)
714       ;; 11: ; r0:r3={RAW,ENC}
715       (branch
716        r3
717        ((write r0) (end))
718        ((write "=")
719         (write r0 ,mel-ccl-high-table)
720         (write r0 ,mel-ccl-low-table)
721         (end)))
722       ;; 12: ; r0:r3={RAW,ENC} r1=CR
723       (branch
724        r3
725        ((write "=\r\n")
726         (write r0)
727         (write "=0D")
728         (end))
729        ((write "=\r\n=")
730         (write r0 ,mel-ccl-high-table)
731         (write r0 ,mel-ccl-low-table)
732         (write "=0D")
733         (end)))
734       ;; 13: r0:r3=RAW CR LF ;
735       (end)
736       ;; 14: r0:r3=ENC CR LF ;
737       (end)
738       ))
739     ))
740
741 (define-ccl-program mel-ccl-decode-quoted-printable
742   `(1
743     ((read r0)
744      (loop
745       (branch
746        r0
747        ,@(mapcar
748           (lambda (r0)
749             (let ((tmp (aref mel-ccl-qp-table r0)))
750               (cond
751                ((or (eq tmp 'raw) (eq tmp 'wsp)) `(write-read-repeat r0))
752                ((eq r0 ?=)
753                 ;; r0='='
754                 `((read r0)
755                   ;; '=' r0
756                   (r1 = (r0 == ?\t))
757                   (if ((r0 == ? ) | r1)
758                       ;; '=' r0:[\t ]
759                       ;; Skip transport-padding.
760                       ;; It should check CR LF after
761                       ;; transport-padding.
762                       (loop
763                        (read-if (r0 == ?\t)
764                                 (repeat)
765                                 (if (r0 == ? )
766                                     (repeat)
767                                   (break)))))
768                   ;; '=' [\t ]* r0:[^\t ]
769                   (branch
770                    r0
771                    ,@(mapcar
772                       (lambda (r0)
773                         (cond
774                          ((eq r0 ?\r)
775                           ;; '=' [\t ]* r0='\r'
776                           `((read r0)
777                             ;; '=' [\t ]* '\r' r0
778                             (if (r0 == ?\n)
779                                 ;; '=' [\t ]* '\r' r0='\n'
780                                 ;; soft line break found.
781                                 ((read r0)
782                                  (repeat))
783                               ;; '=' [\t ]* '\r' r0:[^\n]
784                               ;; invalid input ->
785                               ;; output "=\r" and rescan from r0.
786                               ((write "=\r")
787                                (repeat)))))
788                          ((setq tmp (nth r0 mel-ccl-256-to-16-table))
789                           ;; '=' [\t ]* r0:[0-9A-F]
790                           `(r0 = ,tmp))
791                          (t
792                           ;; '=' [\t ]* r0:[^\r0-9A-F]
793                           ;; invalid input ->
794                           ;; output "=" and rescan from r0.
795                           `((write ?=)
796                             (repeat)))))
797                       mel-ccl-256-table))
798                   ;; '=' [\t ]* r0:[0-9A-F]
799                   (read-branch
800                    r1
801                    ,@(mapcar
802                       (lambda (r1)
803                         (if (setq tmp (nth r1 mel-ccl-256-to-16-table))
804                             ;; '=' [\t ]* [0-9A-F] r1:[0-9A-F]
805                             `(write-read-repeat
806                               r0
807                               ,(vconcat
808                                 (mapcar
809                                  (lambda (r0)
810                                    (logior (lsh r0 4) tmp))
811                                  mel-ccl-16-table)))
812                           ;; '=' [\t ]* [0-9A-F] r1:[^0-9A-F]
813                           ;; invalid input
814                           `(r2 = 0)     ; nop
815                           ))
816                       mel-ccl-256-table))
817                   ;; '=' [\t ]* [0-9A-F] r1:[^0-9A-F]
818                   ;; invalid input
819                   (write ?=)
820                   (write r0 ,(vconcat mel-ccl-16-to-256-table))
821                   (write r1)
822                   (read r0)
823                   (repeat)))
824                ((eq tmp 'cr)
825                 ;; r0='\r'
826                 `((read r0)
827                   ;; '\r' r0
828                   (if (r0 == ?\n)
829                       ;; '\r' r0='\n'
830                       ;; hard line break found.
831                       ((write ?\r)
832                        (write-read-repeat r0))
833                     ;; '\r' r0:[^\n]
834                     ;; invalid control character (bare CR) found.
835                     ;; -> ignore it and rescan from r0.
836                     (repeat))))
837                (t
838                 ;; r0:[^\t\r -~]
839                 ;; invalid character found.
840                 ;; -> ignore.
841                 `((read r0)
842                   (repeat))))))
843           mel-ccl-256-table))))))
844
845
846 ;;; @ coding system
847 ;;;
848
849 (make-ccl-coding-system
850  'mel-ccl-uq ?Q "MIME Q-encoding in unstructured field"
851  'mel-ccl-decode-q 'mel-ccl-encode-uq)
852
853 (make-ccl-coding-system
854  'mel-ccl-cq ?Q "MIME Q-encoding in comment"
855  'mel-ccl-decode-q 'mel-ccl-encode-cq)
856
857 (make-ccl-coding-system
858  'mel-ccl-pq ?Q "MIME Q-encoding in phrase"
859  'mel-ccl-decode-q 'mel-ccl-encode-pq)
860
861 (make-ccl-coding-system
862  'mel-ccl-b ?B "MIME B-encoding"
863  'mel-ccl-decode-b 'mel-ccl-encode-b)
864
865 (make-ccl-coding-system
866  'mel-ccl-quoted-printable ?Q "MIME Quoted-Printable-encoding"
867  'mel-ccl-decode-quoted-printable 'mel-ccl-encode-quoted-printable)
868
869 (make-ccl-coding-system
870  'mel-ccl-base64 ?B "MIME Base64-encoding"
871  'mel-ccl-decode-b 'mel-ccl-encode-base64)
872
873 (make-ccl-coding-system
874  'mel-ccl-b-rev ?B "MIME B-encoding (reversed)"
875  'mel-ccl-encode-b 'mel-ccl-decode-b)
876
877 (make-ccl-coding-system
878  'mel-ccl-quoted-printable-rev ?Q "MIME Quoted-Printable-encoding (reversed)"
879  'mel-ccl-encode-quoted-printable 'mel-ccl-decode-quoted-printable)
880
881 (make-ccl-coding-system
882  'mel-ccl-base64-rev ?B "MIME Base64-encoding (reversed)"
883  'mel-ccl-encode-base64 'mel-ccl-decode-b)
884
885
886 ;;; @ B
887 ;;;
888
889 (unless (and (boundp 'ccl-encoder-eof-block-is-broken)
890              ccl-encoder-eof-block-is-broken)
891
892 (defun base64-ccl-encode-string (string)
893   "Encode STRING with base64 encoding."
894   (encode-coding-string string 'mel-ccl-b))
895
896 (defun base64-ccl-encode-region (start end)
897   "Encode region from START to END with base64 encoding."
898   (interactive "r")
899   (encode-coding-region start end 'mel-ccl-b))
900
901 (defun base64-ccl-insert-encoded-file (filename)
902   "Encode contents of file FILENAME to base64, and insert the result."
903   (interactive (list (read-file-name "Insert encoded file: ")))
904   (let ((coding-system-for-read 'mel-ccl-b))
905     (insert-file-contents filename)))
906
907 )
908
909 (defun base64-ccl-decode-string (string)
910   "Decode base64 encoded STRING"
911   (string-as-unibyte (decode-coding-string string 'mel-ccl-b)))
912
913 (defun base64-ccl-decode-region (start end)
914   "Decode base64 encoded the region from START to END."
915   (interactive "r")
916   (decode-coding-region start end 'mel-ccl-b))
917
918 (defun base64-ccl-write-decoded-region (start end filename)
919   "Decode the region from START to END and write out to FILENAME."
920   (interactive
921     (list (region-beginning) (region-end)
922           (read-file-name "Write decoded region to file: ")))
923   (let ((coding-system-for-write 'mel-ccl-b-rev))
924     (write-region start end filename)))
925
926
927 ;;; @ quoted-printable
928 ;;;
929
930 (unless (and (boundp 'ccl-encoder-eof-block-is-broken)
931              ccl-encoder-eof-block-is-broken)
932
933 (defun quoted-printable-ccl-encode-string (string)
934   "Encode STRING with quoted-printable encoding."
935   (decode-coding-string
936    (encode-coding-string
937     (encode-coding-string
938      string
939      'raw-text-dos)
940     'mel-ccl-quoted-printable)
941    'raw-text-dos))
942
943 (defun quoted-printable-ccl-encode-region (start end)
944   "Encode the region from START to END with quoted-printable
945 encoding."
946   (interactive "r")
947   (setq end (+ start (encode-coding-region start end 'raw-text-dos)))
948   (setq end (+ start (encode-coding-region start end 'mel-ccl-quoted-printable)))
949   (decode-coding-region start end 'raw-text-dos))
950
951 (defun quoted-printable-ccl-insert-encoded-file (filename)
952   "Encode contents of the file named as FILENAME, and insert it."
953   (interactive (list (read-file-name "Insert encoded file: ")))
954   (let ((start (point)) end
955         (coding-system-for-read 'mel-ccl-quoted-printable-rev))
956     (setq end (+ start (cadr (insert-file-contents filename))))
957     (decode-coding-region start end 'raw-text-dos)))
958
959 )
960
961 (defun quoted-printable-ccl-decode-string (string)
962   "Decode quoted-printable encoded STRING."
963   (decode-coding-string
964    (decode-coding-string
965     (encode-coding-string
966      string
967      'raw-text-dos)
968     'mel-ccl-quoted-printable)
969    'raw-text-dos))
970
971 (defun quoted-printable-ccl-decode-region (start end)
972   "Decode the region from START to END with quoted-printable
973 encoding."
974   (interactive "r")
975   (setq end (+ start (encode-coding-region start end 'raw-text-dos)))
976   (setq end (+ start (decode-coding-region start end 'mel-ccl-quoted-printable)))
977   (decode-coding-region start end 'raw-text-dos))
978   
979 (defun quoted-printable-ccl-write-decoded-region
980   (start end filename)
981   "Decode quoted-printable encoded current region and write out to FILENAME."
982   (interactive
983    (list (region-beginning) (region-end)
984          (read-file-name "Write decoded region to file: ")))
985   (let ((buf (current-buffer)) tmp)
986     (with-temp-buffer
987       (setq tmp (current-buffer))
988       (save-excursion
989         (set-buffer buf)
990         (copy-to-buffer tmp start end))
991       (encode-coding-region (point-min) (point-max) 'raw-text-dos)
992       (decode-coding-region (point-min) (point-max) 'mel-ccl-quoted-printable)
993       (decode-coding-region (point-min) (point-max) 'raw-text-dos)
994       (write-region-as-binary (point-min) (point-max) filename))))
995
996
997 ;;; @ Q
998 ;;;
999
1000 (defun q-encoding-ccl-encode-string (string &optional mode)
1001   "Encode STRING to Q-encoding of encoded-word, and return the result.
1002 MODE allows `text', `comment', `phrase' or nil.  Default value is
1003 `phrase'."
1004   (encode-coding-string
1005    string
1006    (cond
1007     ((eq mode 'text) 'mel-ccl-uq)
1008     ((eq mode 'comment) 'mel-ccl-cq)
1009     (t 'mel-ccl-pq))))
1010
1011 (defun q-encoding-ccl-decode-string (string)
1012   "Decode Q encoded STRING and return the result."
1013   (string-as-unibyte
1014    (decode-coding-string
1015     string
1016     'mel-ccl-uq)))
1017
1018
1019 ;;; @ end
1020 ;;;
1021
1022 (provide 'mel-ccl)
1023