LCOV - code coverage report
Current view: top level - src/backend/utils/mb/conversion_procs/euc_jp_and_sjis - euc_jp_and_sjis.c (source / functions) Hit Total Coverage
Test: PostgreSQL 14devel Lines: 167 359 46.5 %
Date: 2021-05-13 09:07:15 Functions: 19 19 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  *    EUC_JP, SJIS and MULE_INTERNAL
       4             :  *
       5             :  * Portions Copyright (c) 1996-2021, 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           8 : PG_MODULE_MAGIC;
      31             : 
      32           4 : PG_FUNCTION_INFO_V1(euc_jp_to_sjis);
      33           4 : PG_FUNCTION_INFO_V1(sjis_to_euc_jp);
      34           4 : PG_FUNCTION_INFO_V1(euc_jp_to_mic);
      35           8 : PG_FUNCTION_INFO_V1(mic_to_euc_jp);
      36           4 : PG_FUNCTION_INFO_V1(sjis_to_mic);
      37           8 : 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 *mic, unsigned char *p, int len, bool noError);
      58             : static int  sjis2euc_jp(const unsigned char *mic, unsigned char *p, int len, bool noError);
      59             : 
      60             : Datum
      61           4 : euc_jp_to_sjis(PG_FUNCTION_ARGS)
      62             : {
      63           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      64           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      65           4 :     int         len = PG_GETARG_INT32(4);
      66           4 :     bool        noError = PG_GETARG_BOOL(5);
      67             :     int         converted;
      68             : 
      69           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JP, PG_SJIS);
      70             : 
      71           4 :     converted = euc_jp2sjis(src, dest, len, noError);
      72             : 
      73           4 :     PG_RETURN_INT32(converted);
      74             : }
      75             : 
      76             : Datum
      77           4 : sjis_to_euc_jp(PG_FUNCTION_ARGS)
      78             : {
      79           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      80           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      81           4 :     int         len = PG_GETARG_INT32(4);
      82           4 :     bool        noError = PG_GETARG_BOOL(5);
      83             :     int         converted;
      84             : 
      85           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_SJIS, PG_EUC_JP);
      86             : 
      87           4 :     converted = sjis2euc_jp(src, dest, len, noError);
      88             : 
      89           4 :     PG_RETURN_INT32(converted);
      90             : }
      91             : 
      92             : Datum
      93           4 : euc_jp_to_mic(PG_FUNCTION_ARGS)
      94             : {
      95           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      96           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      97           4 :     int         len = PG_GETARG_INT32(4);
      98           4 :     bool        noError = PG_GETARG_BOOL(5);
      99             :     int         converted;
     100             : 
     101           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JP, PG_MULE_INTERNAL);
     102             : 
     103           4 :     converted = euc_jp2mic(src, dest, len, noError);
     104             : 
     105           4 :     PG_RETURN_INT32(converted);
     106             : }
     107             : 
     108             : Datum
     109         220 : mic_to_euc_jp(PG_FUNCTION_ARGS)
     110             : {
     111         220 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     112         220 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     113         220 :     int         len = PG_GETARG_INT32(4);
     114         220 :     bool        noError = PG_GETARG_BOOL(5);
     115             :     int         converted;
     116             : 
     117         220 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_JP);
     118             : 
     119         220 :     converted = mic2euc_jp(src, dest, len, noError);
     120             : 
     121         124 :     PG_RETURN_INT32(converted);
     122             : }
     123             : 
     124             : Datum
     125           4 : sjis_to_mic(PG_FUNCTION_ARGS)
     126             : {
     127           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     128           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     129           4 :     int         len = PG_GETARG_INT32(4);
     130           4 :     bool        noError = PG_GETARG_BOOL(5);
     131             :     int         converted;
     132             : 
     133           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_SJIS, PG_MULE_INTERNAL);
     134             : 
     135           4 :     converted = sjis2mic(src, dest, len, noError);
     136             : 
     137           4 :     PG_RETURN_INT32(converted);
     138             : }
     139             : 
     140             : Datum
     141         220 : mic_to_sjis(PG_FUNCTION_ARGS)
     142             : {
     143         220 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     144         220 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     145         220 :     int         len = PG_GETARG_INT32(4);
     146         220 :     bool        noError = PG_GETARG_BOOL(5);
     147             :     int         converted;
     148             : 
     149         220 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_SJIS);
     150             : 
     151         220 :     converted = mic2sjis(src, dest, len, noError);
     152             : 
     153         124 :     PG_RETURN_INT32(converted);
     154             : }
     155             : 
     156             : /*
     157             :  * SJIS ---> MIC
     158             :  */
     159             : static int
     160           4 : sjis2mic(const unsigned char *sjis, unsigned char *p, int len, bool noError)
     161             : {
     162           4 :     const unsigned char *start = sjis;
     163             :     int         c1,
     164             :                 c2,
     165             :                 i,
     166             :                 k,
     167             :                 k2;
     168             : 
     169          16 :     while (len > 0)
     170             :     {
     171          12 :         c1 = *sjis;
     172          12 :         if (c1 >= 0xa1 && c1 <= 0xdf)
     173             :         {
     174             :             /* JIS X0201 (1 byte kana) */
     175           0 :             *p++ = LC_JISX0201K;
     176           0 :             *p++ = c1;
     177           0 :             sjis++;
     178           0 :             len--;
     179             :         }
     180          12 :         else if (IS_HIGHBIT_SET(c1))
     181             :         {
     182             :             /*
     183             :              * JIS X0208, X0212, user defined extended characters
     184             :              */
     185           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          12 :             if (c1 == 0)
     280             :             {
     281           0 :                 if (noError)
     282           0 :                     break;
     283           0 :                 report_invalid_encoding(PG_SJIS, (const char *) sjis, len);
     284             :             }
     285          12 :             *p++ = c1;
     286          12 :             sjis++;
     287          12 :             len--;
     288             :         }
     289             :     }
     290           4 :     *p = '\0';
     291             : 
     292           4 :     return sjis - start;
     293             : }
     294             : 
     295             : /*
     296             :  * MIC ---> SJIS
     297             :  */
     298             : static int
     299         220 : mic2sjis(const unsigned char *mic, unsigned char *p, int len, bool noError)
     300             : {
     301         220 :     const unsigned char *start = mic;
     302             :     int         c1,
     303             :                 c2,
     304             :                 k,
     305             :                 l;
     306             : 
     307         448 :     while (len > 0)
     308             :     {
     309         420 :         c1 = *mic;
     310         420 :         if (!IS_HIGHBIT_SET(c1))
     311             :         {
     312             :             /* ASCII */
     313         216 :             if (c1 == 0)
     314             :             {
     315          24 :                 if (noError)
     316          12 :                     break;
     317          12 :                 report_invalid_encoding(PG_MULE_INTERNAL,
     318             :                                         (const char *) mic, len);
     319             :             }
     320         192 :             *p++ = c1;
     321         192 :             mic++;
     322         192 :             len--;
     323         192 :             continue;
     324             :         }
     325         204 :         l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
     326         204 :         if (l < 0)
     327             :         {
     328          96 :             if (noError)
     329          48 :                 break;
     330          48 :             report_invalid_encoding(PG_MULE_INTERNAL,
     331             :                                     (const char *) mic, len);
     332             :         }
     333         108 :         if (c1 == LC_JISX0201K)
     334           0 :             *p++ = mic[1];
     335         108 :         else if (c1 == LC_JISX0208)
     336             :         {
     337          36 :             c1 = mic[1];
     338          36 :             c2 = mic[2];
     339          36 :             k = (c1 << 8) | (c2 & 0xff);
     340          36 :             if (k >= 0xf5a1)
     341             :             {
     342             :                 /* UDC1 */
     343           0 :                 c1 -= 0x54;
     344           0 :                 *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x6f;
     345             :             }
     346             :             else
     347          36 :                 *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1);
     348          36 :             *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
     349             :         }
     350          72 :         else if (c1 == LC_JISX0212)
     351             :         {
     352             :             int         i,
     353             :                         k2;
     354             : 
     355           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          72 :             if (noError)
     390          36 :                 break;
     391          36 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_SJIS,
     392             :                                        (const char *) mic, len);
     393             :         }
     394          36 :         mic += l;
     395          36 :         len -= l;
     396             :     }
     397         124 :     *p = '\0';
     398             : 
     399         124 :     return mic - start;
     400             : }
     401             : 
     402             : /*
     403             :  * EUC_JP ---> MIC
     404             :  */
     405             : static int
     406           4 : euc_jp2mic(const unsigned char *euc, unsigned char *p, int len, bool noError)
     407             : {
     408           4 :     const unsigned char *start = euc;
     409             :     int         c1;
     410             :     int         l;
     411             : 
     412          16 :     while (len > 0)
     413             :     {
     414          12 :         c1 = *euc;
     415          12 :         if (!IS_HIGHBIT_SET(c1))
     416             :         {
     417             :             /* ASCII */
     418          12 :             if (c1 == 0)
     419             :             {
     420           0 :                 if (noError)
     421           0 :                     break;
     422           0 :                 report_invalid_encoding(PG_EUC_JP,
     423             :                                         (const char *) euc, len);
     424             :             }
     425          12 :             *p++ = c1;
     426          12 :             euc++;
     427          12 :             len--;
     428          12 :             continue;
     429             :         }
     430           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           4 :     *p = '\0';
     459             : 
     460           4 :     return euc - start;
     461             : }
     462             : 
     463             : /*
     464             :  * MIC ---> EUC_JP
     465             :  */
     466             : static int
     467         220 : mic2euc_jp(const unsigned char *mic, unsigned char *p, int len, bool noError)
     468             : {
     469         220 :     const unsigned char *start = mic;
     470             :     int         c1;
     471             :     int         l;
     472             : 
     473         448 :     while (len > 0)
     474             :     {
     475         420 :         c1 = *mic;
     476         420 :         if (!IS_HIGHBIT_SET(c1))
     477             :         {
     478             :             /* ASCII */
     479         216 :             if (c1 == 0)
     480             :             {
     481          24 :                 if (noError)
     482          12 :                     break;
     483          12 :                 report_invalid_encoding(PG_MULE_INTERNAL,
     484             :                                         (const char *) mic, len);
     485             :             }
     486         192 :             *p++ = c1;
     487         192 :             mic++;
     488         192 :             len--;
     489         192 :             continue;
     490             :         }
     491         204 :         l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
     492         204 :         if (l < 0)
     493             :         {
     494          96 :             if (noError)
     495          48 :                 break;
     496          48 :             report_invalid_encoding(PG_MULE_INTERNAL,
     497             :                                     (const char *) mic, len);
     498             :         }
     499         108 :         if (c1 == LC_JISX0201K)
     500             :         {
     501           0 :             *p++ = SS2;
     502           0 :             *p++ = mic[1];
     503             :         }
     504         108 :         else if (c1 == LC_JISX0212)
     505             :         {
     506           0 :             *p++ = SS3;
     507           0 :             *p++ = mic[1];
     508           0 :             *p++ = mic[2];
     509             :         }
     510         108 :         else if (c1 == LC_JISX0208)
     511             :         {
     512          36 :             *p++ = mic[1];
     513          36 :             *p++ = mic[2];
     514             :         }
     515             :         else
     516             :         {
     517          72 :             if (noError)
     518          36 :                 break;
     519          36 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_JP,
     520             :                                        (const char *) mic, len);
     521             :         }
     522          36 :         mic += l;
     523          36 :         len -= l;
     524             :     }
     525         124 :     *p = '\0';
     526             : 
     527         124 :     return mic - start;
     528             : }
     529             : 
     530             : /*
     531             :  * EUC_JP -> SJIS
     532             :  */
     533             : static int
     534           4 : euc_jp2sjis(const unsigned char *euc, unsigned char *p, int len, bool noError)
     535             : {
     536           4 :     const unsigned char *start = euc;
     537             :     int         c1,
     538             :                 c2,
     539             :                 k;
     540             :     int         l;
     541             : 
     542          16 :     while (len > 0)
     543             :     {
     544          12 :         c1 = *euc;
     545          12 :         if (!IS_HIGHBIT_SET(c1))
     546             :         {
     547             :             /* ASCII */
     548          12 :             if (c1 == 0)
     549             :             {
     550           0 :                 if (noError)
     551           0 :                     break;
     552           0 :                 report_invalid_encoding(PG_EUC_JP,
     553             :                                         (const char *) euc, len);
     554             :             }
     555          12 :             *p++ = c1;
     556          12 :             euc++;
     557          12 :             len--;
     558          12 :             continue;
     559             :         }
     560           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           4 :     *p = '\0';
     630             : 
     631           4 :     return euc - start;
     632             : }
     633             : 
     634             : /*
     635             :  * SJIS ---> EUC_JP
     636             :  */
     637             : static int
     638           4 : sjis2euc_jp(const unsigned char *sjis, unsigned char *p, int len, bool noError)
     639             : {
     640           4 :     const unsigned char *start = sjis;
     641             :     int         c1,
     642             :                 c2,
     643             :                 i,
     644             :                 k,
     645             :                 k2;
     646             :     int         l;
     647             : 
     648          16 :     while (len > 0)
     649             :     {
     650          12 :         c1 = *sjis;
     651          12 :         if (!IS_HIGHBIT_SET(c1))
     652             :         {
     653             :             /* ASCII */
     654          12 :             if (c1 == 0)
     655             :             {
     656           0 :                 if (noError)
     657           0 :                     break;
     658           0 :                 report_invalid_encoding(PG_SJIS,
     659             :                                         (const char *) sjis, len);
     660             :             }
     661          12 :             *p++ = c1;
     662          12 :             sjis++;
     663          12 :             len--;
     664          12 :             continue;
     665             :         }
     666           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           4 :     *p = '\0';
     770             : 
     771           4 :     return sjis - start;
     772             : }

Generated by: LCOV version 1.13