TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * EUC_JP, SJIS and MULE_INTERNAL
4 : *
5 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
6 : * Portions Copyright (c) 1994, Regents of the University of California
7 : *
8 : * IDENTIFICATION
9 : * src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c
10 : *
11 : *-------------------------------------------------------------------------
12 : */
13 :
14 : #include "postgres.h"
15 : #include "fmgr.h"
16 : #include "mb/pg_wchar.h"
17 :
18 : /*
19 : * SJIS alternative code.
20 : * this code is used if a mapping EUC -> SJIS is not defined.
21 : */
22 : #define PGSJISALTCODE 0x81ac
23 : #define PGEUCALTCODE 0xa2ae
24 :
25 : /*
26 : * conversion table between SJIS UDC (IBM kanji) and EUC_JP
27 : */
28 : #include "sjis.map"
29 :
30 CBC 6 : PG_MODULE_MAGIC;
31 :
32 3 : PG_FUNCTION_INFO_V1(euc_jp_to_sjis);
33 3 : PG_FUNCTION_INFO_V1(sjis_to_euc_jp);
34 3 : PG_FUNCTION_INFO_V1(euc_jp_to_mic);
35 6 : PG_FUNCTION_INFO_V1(mic_to_euc_jp);
36 3 : PG_FUNCTION_INFO_V1(sjis_to_mic);
37 6 : PG_FUNCTION_INFO_V1(mic_to_sjis);
38 :
39 : /* ----------
40 : * conv_proc(
41 : * INTEGER, -- source encoding id
42 : * INTEGER, -- destination encoding id
43 : * CSTRING, -- source string (null terminated C string)
44 : * CSTRING, -- destination string (null terminated C string)
45 : * INTEGER, -- source string length
46 : * BOOL -- if true, don't throw an error if conversion fails
47 : * ) returns INTEGER;
48 : *
49 : * Returns the number of bytes successfully converted.
50 : * ----------
51 : */
52 :
53 : static int sjis2mic(const unsigned char *sjis, unsigned char *p, int len, bool noError);
54 : static int mic2sjis(const unsigned char *mic, unsigned char *p, int len, bool noError);
55 : static int euc_jp2mic(const unsigned char *euc, unsigned char *p, int len, bool noError);
56 : static int mic2euc_jp(const unsigned char *mic, unsigned char *p, int len, bool noError);
57 : static int euc_jp2sjis(const unsigned char *euc, unsigned char *p, int len, bool noError);
58 : static int sjis2euc_jp(const unsigned char *sjis, unsigned char *p, int len, bool noError);
59 :
60 : Datum
61 3 : euc_jp_to_sjis(PG_FUNCTION_ARGS)
62 : {
63 3 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
64 3 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
65 3 : int len = PG_GETARG_INT32(4);
66 3 : bool noError = PG_GETARG_BOOL(5);
67 : int converted;
68 :
69 3 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JP, PG_SJIS);
70 :
71 3 : converted = euc_jp2sjis(src, dest, len, noError);
72 :
73 3 : PG_RETURN_INT32(converted);
74 : }
75 :
76 : Datum
77 3 : sjis_to_euc_jp(PG_FUNCTION_ARGS)
78 : {
79 3 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
80 3 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
81 3 : int len = PG_GETARG_INT32(4);
82 3 : bool noError = PG_GETARG_BOOL(5);
83 : int converted;
84 :
85 3 : CHECK_ENCODING_CONVERSION_ARGS(PG_SJIS, PG_EUC_JP);
86 :
87 3 : converted = sjis2euc_jp(src, dest, len, noError);
88 :
89 3 : PG_RETURN_INT32(converted);
90 : }
91 :
92 : Datum
93 3 : euc_jp_to_mic(PG_FUNCTION_ARGS)
94 : {
95 3 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
96 3 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
97 3 : int len = PG_GETARG_INT32(4);
98 3 : bool noError = PG_GETARG_BOOL(5);
99 : int converted;
100 :
101 3 : CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JP, PG_MULE_INTERNAL);
102 :
103 3 : converted = euc_jp2mic(src, dest, len, noError);
104 :
105 3 : PG_RETURN_INT32(converted);
106 : }
107 :
108 : Datum
109 165 : mic_to_euc_jp(PG_FUNCTION_ARGS)
110 : {
111 165 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
112 165 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
113 165 : int len = PG_GETARG_INT32(4);
114 165 : bool noError = PG_GETARG_BOOL(5);
115 : int converted;
116 :
117 165 : CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_JP);
118 :
119 165 : converted = mic2euc_jp(src, dest, len, noError);
120 :
121 93 : PG_RETURN_INT32(converted);
122 : }
123 :
124 : Datum
125 3 : sjis_to_mic(PG_FUNCTION_ARGS)
126 : {
127 3 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
128 3 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
129 3 : int len = PG_GETARG_INT32(4);
130 3 : bool noError = PG_GETARG_BOOL(5);
131 : int converted;
132 :
133 3 : CHECK_ENCODING_CONVERSION_ARGS(PG_SJIS, PG_MULE_INTERNAL);
134 :
135 3 : converted = sjis2mic(src, dest, len, noError);
136 :
137 3 : PG_RETURN_INT32(converted);
138 : }
139 :
140 : Datum
141 165 : mic_to_sjis(PG_FUNCTION_ARGS)
142 : {
143 165 : unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
144 165 : unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
145 165 : int len = PG_GETARG_INT32(4);
146 165 : bool noError = PG_GETARG_BOOL(5);
147 : int converted;
148 :
149 165 : CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_SJIS);
150 :
151 165 : converted = mic2sjis(src, dest, len, noError);
152 :
153 93 : PG_RETURN_INT32(converted);
154 : }
155 :
156 : /*
157 : * SJIS ---> MIC
158 : */
159 : static int
160 3 : sjis2mic(const unsigned char *sjis, unsigned char *p, int len, bool noError)
161 : {
162 3 : const unsigned char *start = sjis;
163 : int c1,
164 : c2,
165 : i,
166 : k,
167 : k2;
168 :
169 12 : while (len > 0)
170 : {
171 9 : c1 = *sjis;
172 9 : if (c1 >= 0xa1 && c1 <= 0xdf)
173 : {
174 : /* JIS X0201 (1 byte kana) */
175 UBC 0 : *p++ = LC_JISX0201K;
176 0 : *p++ = c1;
177 0 : sjis++;
178 0 : len--;
179 : }
180 CBC 9 : else if (IS_HIGHBIT_SET(c1))
181 : {
182 : /*
183 : * JIS X0208, X0212, user defined extended characters
184 : */
185 UBC 0 : if (len < 2 || !ISSJISHEAD(c1) || !ISSJISTAIL(sjis[1]))
186 : {
187 0 : if (noError)
188 0 : break;
189 0 : report_invalid_encoding(PG_SJIS, (const char *) sjis, len);
190 : }
191 0 : c2 = sjis[1];
192 0 : k = (c1 << 8) + c2;
193 0 : if (k >= 0xed40 && k < 0xf040)
194 : {
195 : /* NEC selection IBM kanji */
196 0 : for (i = 0;; i++)
197 : {
198 0 : k2 = ibmkanji[i].nec;
199 0 : if (k2 == 0xffff)
200 0 : break;
201 0 : if (k2 == k)
202 : {
203 0 : k = ibmkanji[i].sjis;
204 0 : c1 = (k >> 8) & 0xff;
205 0 : c2 = k & 0xff;
206 : }
207 : }
208 : }
209 :
210 0 : if (k < 0xeb3f)
211 : {
212 : /* JIS X0208 */
213 0 : *p++ = LC_JISX0208;
214 0 : *p++ = ((c1 & 0x3f) << 1) + 0x9f + (c2 > 0x9e);
215 0 : *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
216 : }
217 0 : else if ((k >= 0xeb40 && k < 0xf040) || (k >= 0xfc4c && k <= 0xfcfc))
218 : {
219 : /* NEC selection IBM kanji - Other undecided justice */
220 0 : *p++ = LC_JISX0208;
221 0 : *p++ = PGEUCALTCODE >> 8;
222 0 : *p++ = PGEUCALTCODE & 0xff;
223 : }
224 0 : else if (k >= 0xf040 && k < 0xf540)
225 : {
226 : /*
227 : * UDC1 mapping to X0208 85 ku - 94 ku JIS code 0x7521 -
228 : * 0x7e7e EUC 0xf5a1 - 0xfefe
229 : */
230 0 : *p++ = LC_JISX0208;
231 0 : c1 -= 0x6f;
232 0 : *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
233 0 : *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
234 : }
235 0 : else if (k >= 0xf540 && k < 0xfa40)
236 : {
237 : /*
238 : * UDC2 mapping to X0212 85 ku - 94 ku JIS code 0x7521 -
239 : * 0x7e7e EUC 0x8ff5a1 - 0x8ffefe
240 : */
241 0 : *p++ = LC_JISX0212;
242 0 : c1 -= 0x74;
243 0 : *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
244 0 : *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
245 : }
246 0 : else if (k >= 0xfa40)
247 : {
248 : /*
249 : * mapping IBM kanji to X0208 and X0212
250 : */
251 0 : for (i = 0;; i++)
252 : {
253 0 : k2 = ibmkanji[i].sjis;
254 0 : if (k2 == 0xffff)
255 0 : break;
256 0 : if (k2 == k)
257 : {
258 0 : k = ibmkanji[i].euc;
259 0 : if (k >= 0x8f0000)
260 : {
261 0 : *p++ = LC_JISX0212;
262 0 : *p++ = 0x80 | ((k & 0xff00) >> 8);
263 0 : *p++ = 0x80 | (k & 0xff);
264 : }
265 : else
266 : {
267 0 : *p++ = LC_JISX0208;
268 0 : *p++ = 0x80 | (k >> 8);
269 0 : *p++ = 0x80 | (k & 0xff);
270 : }
271 : }
272 : }
273 : }
274 0 : sjis += 2;
275 0 : len -= 2;
276 : }
277 : else
278 : { /* should be ASCII */
279 CBC 9 : if (c1 == 0)
280 : {
281 UBC 0 : if (noError)
282 0 : break;
283 0 : report_invalid_encoding(PG_SJIS, (const char *) sjis, len);
284 : }
285 CBC 9 : *p++ = c1;
286 9 : sjis++;
287 9 : len--;
288 : }
289 : }
290 3 : *p = '\0';
291 :
292 3 : return sjis - start;
293 : }
294 :
295 : /*
296 : * MIC ---> SJIS
297 : */
298 : static int
299 165 : mic2sjis(const unsigned char *mic, unsigned char *p, int len, bool noError)
300 : {
301 165 : const unsigned char *start = mic;
302 : int c1,
303 : c2,
304 : k,
305 : l;
306 :
307 336 : while (len > 0)
308 : {
309 315 : c1 = *mic;
310 315 : if (!IS_HIGHBIT_SET(c1))
311 : {
312 : /* ASCII */
313 162 : if (c1 == 0)
314 : {
315 18 : if (noError)
316 9 : break;
317 9 : report_invalid_encoding(PG_MULE_INTERNAL,
318 : (const char *) mic, len);
319 : }
320 144 : *p++ = c1;
321 144 : mic++;
322 144 : len--;
323 144 : continue;
324 : }
325 153 : l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
326 153 : if (l < 0)
327 : {
328 72 : if (noError)
329 36 : break;
330 36 : report_invalid_encoding(PG_MULE_INTERNAL,
331 : (const char *) mic, len);
332 : }
333 81 : if (c1 == LC_JISX0201K)
334 UBC 0 : *p++ = mic[1];
335 CBC 81 : else if (c1 == LC_JISX0208)
336 : {
337 27 : c1 = mic[1];
338 27 : c2 = mic[2];
339 27 : k = (c1 << 8) | (c2 & 0xff);
340 27 : if (k >= 0xf5a1)
341 : {
342 : /* UDC1 */
343 UBC 0 : c1 -= 0x54;
344 0 : *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x6f;
345 : }
346 : else
347 CBC 27 : *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1);
348 27 : *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
349 : }
350 54 : else if (c1 == LC_JISX0212)
351 : {
352 : int i,
353 : k2;
354 :
355 UBC 0 : c1 = mic[1];
356 0 : c2 = mic[2];
357 0 : k = c1 << 8 | c2;
358 0 : if (k >= 0xf5a1)
359 : {
360 : /* UDC2 */
361 0 : c1 -= 0x54;
362 0 : *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x74;
363 0 : *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
364 : }
365 : else
366 : {
367 : /* IBM kanji */
368 0 : for (i = 0;; i++)
369 : {
370 0 : k2 = ibmkanji[i].euc & 0xffff;
371 0 : if (k2 == 0xffff)
372 : {
373 0 : *p++ = PGSJISALTCODE >> 8;
374 0 : *p++ = PGSJISALTCODE & 0xff;
375 0 : break;
376 : }
377 0 : if (k2 == k)
378 : {
379 0 : k = ibmkanji[i].sjis;
380 0 : *p++ = k >> 8;
381 0 : *p++ = k & 0xff;
382 0 : break;
383 : }
384 : }
385 : }
386 : }
387 : else
388 : {
389 CBC 54 : if (noError)
390 27 : break;
391 27 : report_untranslatable_char(PG_MULE_INTERNAL, PG_SJIS,
392 : (const char *) mic, len);
393 : }
394 27 : mic += l;
395 27 : len -= l;
396 : }
397 93 : *p = '\0';
398 :
399 93 : return mic - start;
400 : }
401 :
402 : /*
403 : * EUC_JP ---> MIC
404 : */
405 : static int
406 3 : euc_jp2mic(const unsigned char *euc, unsigned char *p, int len, bool noError)
407 : {
408 3 : const unsigned char *start = euc;
409 : int c1;
410 : int l;
411 :
412 12 : while (len > 0)
413 : {
414 9 : c1 = *euc;
415 9 : if (!IS_HIGHBIT_SET(c1))
416 : {
417 : /* ASCII */
418 9 : if (c1 == 0)
419 : {
420 UBC 0 : if (noError)
421 0 : break;
422 0 : report_invalid_encoding(PG_EUC_JP,
423 : (const char *) euc, len);
424 : }
425 CBC 9 : *p++ = c1;
426 9 : euc++;
427 9 : len--;
428 9 : continue;
429 : }
430 UBC 0 : l = pg_encoding_verifymbchar(PG_EUC_JP, (const char *) euc, len);
431 0 : if (l < 0)
432 : {
433 0 : if (noError)
434 0 : break;
435 0 : report_invalid_encoding(PG_EUC_JP,
436 : (const char *) euc, len);
437 : }
438 0 : if (c1 == SS2)
439 : { /* 1 byte kana? */
440 0 : *p++ = LC_JISX0201K;
441 0 : *p++ = euc[1];
442 : }
443 0 : else if (c1 == SS3)
444 : { /* JIS X0212 kanji? */
445 0 : *p++ = LC_JISX0212;
446 0 : *p++ = euc[1];
447 0 : *p++ = euc[2];
448 : }
449 : else
450 : { /* kanji? */
451 0 : *p++ = LC_JISX0208;
452 0 : *p++ = c1;
453 0 : *p++ = euc[1];
454 : }
455 0 : euc += l;
456 0 : len -= l;
457 : }
458 CBC 3 : *p = '\0';
459 :
460 3 : return euc - start;
461 : }
462 :
463 : /*
464 : * MIC ---> EUC_JP
465 : */
466 : static int
467 165 : mic2euc_jp(const unsigned char *mic, unsigned char *p, int len, bool noError)
468 : {
469 165 : const unsigned char *start = mic;
470 : int c1;
471 : int l;
472 :
473 336 : while (len > 0)
474 : {
475 315 : c1 = *mic;
476 315 : if (!IS_HIGHBIT_SET(c1))
477 : {
478 : /* ASCII */
479 162 : if (c1 == 0)
480 : {
481 18 : if (noError)
482 9 : break;
483 9 : report_invalid_encoding(PG_MULE_INTERNAL,
484 : (const char *) mic, len);
485 : }
486 144 : *p++ = c1;
487 144 : mic++;
488 144 : len--;
489 144 : continue;
490 : }
491 153 : l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
492 153 : if (l < 0)
493 : {
494 72 : if (noError)
495 36 : break;
496 36 : report_invalid_encoding(PG_MULE_INTERNAL,
497 : (const char *) mic, len);
498 : }
499 81 : if (c1 == LC_JISX0201K)
500 : {
501 UBC 0 : *p++ = SS2;
502 0 : *p++ = mic[1];
503 : }
504 CBC 81 : else if (c1 == LC_JISX0212)
505 : {
506 UBC 0 : *p++ = SS3;
507 0 : *p++ = mic[1];
508 0 : *p++ = mic[2];
509 : }
510 CBC 81 : else if (c1 == LC_JISX0208)
511 : {
512 27 : *p++ = mic[1];
513 27 : *p++ = mic[2];
514 : }
515 : else
516 : {
517 54 : if (noError)
518 27 : break;
519 27 : report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_JP,
520 : (const char *) mic, len);
521 : }
522 27 : mic += l;
523 27 : len -= l;
524 : }
525 93 : *p = '\0';
526 :
527 93 : return mic - start;
528 : }
529 :
530 : /*
531 : * EUC_JP -> SJIS
532 : */
533 : static int
534 3 : euc_jp2sjis(const unsigned char *euc, unsigned char *p, int len, bool noError)
535 : {
536 3 : const unsigned char *start = euc;
537 : int c1,
538 : c2,
539 : k;
540 : int l;
541 :
542 12 : while (len > 0)
543 : {
544 9 : c1 = *euc;
545 9 : if (!IS_HIGHBIT_SET(c1))
546 : {
547 : /* ASCII */
548 9 : if (c1 == 0)
549 : {
550 UBC 0 : if (noError)
551 0 : break;
552 0 : report_invalid_encoding(PG_EUC_JP,
553 : (const char *) euc, len);
554 : }
555 CBC 9 : *p++ = c1;
556 9 : euc++;
557 9 : len--;
558 9 : continue;
559 : }
560 UBC 0 : l = pg_encoding_verifymbchar(PG_EUC_JP, (const char *) euc, len);
561 0 : if (l < 0)
562 : {
563 0 : if (noError)
564 0 : break;
565 0 : report_invalid_encoding(PG_EUC_JP,
566 : (const char *) euc, len);
567 : }
568 0 : if (c1 == SS2)
569 : {
570 : /* hankaku kana? */
571 0 : *p++ = euc[1];
572 : }
573 0 : else if (c1 == SS3)
574 : {
575 : /* JIS X0212 kanji? */
576 0 : c1 = euc[1];
577 0 : c2 = euc[2];
578 0 : k = c1 << 8 | c2;
579 0 : if (k >= 0xf5a1)
580 : {
581 : /* UDC2 */
582 0 : c1 -= 0x54;
583 0 : *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x74;
584 0 : *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
585 : }
586 : else
587 : {
588 : int i,
589 : k2;
590 :
591 : /* IBM kanji */
592 0 : for (i = 0;; i++)
593 : {
594 0 : k2 = ibmkanji[i].euc & 0xffff;
595 0 : if (k2 == 0xffff)
596 : {
597 0 : *p++ = PGSJISALTCODE >> 8;
598 0 : *p++ = PGSJISALTCODE & 0xff;
599 0 : break;
600 : }
601 0 : if (k2 == k)
602 : {
603 0 : k = ibmkanji[i].sjis;
604 0 : *p++ = k >> 8;
605 0 : *p++ = k & 0xff;
606 0 : break;
607 : }
608 : }
609 : }
610 : }
611 : else
612 : {
613 : /* JIS X0208 kanji? */
614 0 : c2 = euc[1];
615 0 : k = (c1 << 8) | (c2 & 0xff);
616 0 : if (k >= 0xf5a1)
617 : {
618 : /* UDC1 */
619 0 : c1 -= 0x54;
620 0 : *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x6f;
621 : }
622 : else
623 0 : *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1);
624 0 : *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
625 : }
626 0 : euc += l;
627 0 : len -= l;
628 : }
629 CBC 3 : *p = '\0';
630 :
631 3 : return euc - start;
632 : }
633 :
634 : /*
635 : * SJIS ---> EUC_JP
636 : */
637 : static int
638 3 : sjis2euc_jp(const unsigned char *sjis, unsigned char *p, int len, bool noError)
639 : {
640 3 : const unsigned char *start = sjis;
641 : int c1,
642 : c2,
643 : i,
644 : k,
645 : k2;
646 : int l;
647 :
648 12 : while (len > 0)
649 : {
650 9 : c1 = *sjis;
651 9 : if (!IS_HIGHBIT_SET(c1))
652 : {
653 : /* ASCII */
654 9 : if (c1 == 0)
655 : {
656 UBC 0 : if (noError)
657 0 : break;
658 0 : report_invalid_encoding(PG_SJIS,
659 : (const char *) sjis, len);
660 : }
661 CBC 9 : *p++ = c1;
662 9 : sjis++;
663 9 : len--;
664 9 : continue;
665 : }
666 UBC 0 : l = pg_encoding_verifymbchar(PG_SJIS, (const char *) sjis, len);
667 0 : if (l < 0)
668 : {
669 0 : if (noError)
670 0 : break;
671 0 : report_invalid_encoding(PG_SJIS,
672 : (const char *) sjis, len);
673 : }
674 0 : if (c1 >= 0xa1 && c1 <= 0xdf)
675 : {
676 : /* JIS X0201 (1 byte kana) */
677 0 : *p++ = SS2;
678 0 : *p++ = c1;
679 : }
680 : else
681 : {
682 : /*
683 : * JIS X0208, X0212, user defined extended characters
684 : */
685 0 : c2 = sjis[1];
686 0 : k = (c1 << 8) + c2;
687 0 : if (k >= 0xed40 && k < 0xf040)
688 : {
689 : /* NEC selection IBM kanji */
690 0 : for (i = 0;; i++)
691 : {
692 0 : k2 = ibmkanji[i].nec;
693 0 : if (k2 == 0xffff)
694 0 : break;
695 0 : if (k2 == k)
696 : {
697 0 : k = ibmkanji[i].sjis;
698 0 : c1 = (k >> 8) & 0xff;
699 0 : c2 = k & 0xff;
700 : }
701 : }
702 : }
703 :
704 0 : if (k < 0xeb3f)
705 : {
706 : /* JIS X0208 */
707 0 : *p++ = ((c1 & 0x3f) << 1) + 0x9f + (c2 > 0x9e);
708 0 : *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
709 : }
710 0 : else if ((k >= 0xeb40 && k < 0xf040) || (k >= 0xfc4c && k <= 0xfcfc))
711 : {
712 : /* NEC selection IBM kanji - Other undecided justice */
713 0 : *p++ = PGEUCALTCODE >> 8;
714 0 : *p++ = PGEUCALTCODE & 0xff;
715 : }
716 0 : else if (k >= 0xf040 && k < 0xf540)
717 : {
718 : /*
719 : * UDC1 mapping to X0208 85 ku - 94 ku JIS code 0x7521 -
720 : * 0x7e7e EUC 0xf5a1 - 0xfefe
721 : */
722 0 : c1 -= 0x6f;
723 0 : *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
724 0 : *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
725 : }
726 0 : else if (k >= 0xf540 && k < 0xfa40)
727 : {
728 : /*
729 : * UDC2 mapping to X0212 85 ku - 94 ku JIS code 0x7521 -
730 : * 0x7e7e EUC 0x8ff5a1 - 0x8ffefe
731 : */
732 0 : *p++ = SS3;
733 0 : c1 -= 0x74;
734 0 : *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
735 0 : *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
736 : }
737 0 : else if (k >= 0xfa40)
738 : {
739 : /*
740 : * mapping IBM kanji to X0208 and X0212
741 : *
742 : */
743 0 : for (i = 0;; i++)
744 : {
745 0 : k2 = ibmkanji[i].sjis;
746 0 : if (k2 == 0xffff)
747 0 : break;
748 0 : if (k2 == k)
749 : {
750 0 : k = ibmkanji[i].euc;
751 0 : if (k >= 0x8f0000)
752 : {
753 0 : *p++ = SS3;
754 0 : *p++ = 0x80 | ((k & 0xff00) >> 8);
755 0 : *p++ = 0x80 | (k & 0xff);
756 : }
757 : else
758 : {
759 0 : *p++ = 0x80 | (k >> 8);
760 0 : *p++ = 0x80 | (k & 0xff);
761 : }
762 : }
763 : }
764 : }
765 : }
766 0 : sjis += l;
767 0 : len -= l;
768 : }
769 CBC 3 : *p = '\0';
770 :
771 3 : return sjis - start;
772 : }
|