aboutsummaryrefslogtreecommitdiff
path: root/iconvdata/ibm937.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconvdata/ibm937.c')
-rw-r--r--iconvdata/ibm937.c94
1 files changed, 70 insertions, 24 deletions
diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
index 39468aa0dd..be1d4b92d5 100644
--- a/iconvdata/ibm937.c
+++ b/iconvdata/ibm937.c
@@ -1,4 +1,4 @@
-/* Conversion to and from IBM937.
+/* Conversion from and to IBM937.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
@@ -95,6 +95,7 @@ enum
#define BODY \
{ \
uint32_t ch = *inptr; \
+ uint32_t res; \
\
if (__builtin_expect (ch, 0) == SO) \
{ \
@@ -123,9 +124,9 @@ enum
\
if (curcs == sb) \
{ \
- /* Use the UCS4 table for single byte. */ \
- ch = __ibm937sb_to_ucs4[ch]; \
- if (__builtin_expect (ch, L'\1') == L'\0' && *inptr != '\0') \
+ /* Use the IBM937 table for single byte. */ \
+ res = __ibm937sb_to_ucs4[ch]; \
+ if (__builtin_expect (res, L'\1') == L'\0' && ch != '\0') \
{ \
/* This is an illegal character. */ \
if (! ignore_errors_p ()) \
@@ -137,19 +138,34 @@ enum
} \
else \
{ \
- put32 (outptr, ch); \
+ put32 (outptr, res); \
outptr += 4; \
} \
++inptr; \
} \
else \
{ \
- /* Use the IBM937 table for double byte. */ \
+ const struct gap *rp2 = __ibm937db_to_ucs4_idx; \
\
assert (curcs == db); \
\
- ch = ibm937db_to_ucs4(inptr[0], inptr[1]); \
- if (__builtin_expect (ch, L'\1') == L'\0' && *inptr != '\0') \
+ /* Use the IBM937 table for double byte. */ \
+ if (__builtin_expect (inptr + 1 >= inend, 0)) \
+ { \
+ /* The second character is not available. \
+ Store the intermediate result. */ \
+ result = __GCONV_INCOMPLETE_INPUT; \
+ break; \
+ } \
+ \
+ ch = (ch * 0x100) + inptr[1]; \
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+ if (__builtin_expect (rp2 == NULL, 0) \
+ || __builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm937db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
{ \
/* This is an illegal character. */ \
if (! ignore_errors_p ()) \
@@ -161,7 +177,7 @@ enum
} \
else \
{ \
- put32 (outptr, ch); \
+ put32 (outptr, res); \
outptr += 4; \
} \
inptr += 2; \
@@ -181,22 +197,40 @@ enum
#define BODY \
{ \
uint32_t ch = get32 (inptr); \
+ const struct gap *rp1 = __ucs4_to_ibm937sb_idx; \
+ const struct gap *rp2 = __ucs4_to_ibm937db_idx; \
const char *cp; \
\
- /* Use the UCS4 table for single byte. */ \
- if (__builtin_expect (ch >= (sizeof (__ucs4_to_ibm937sb) \
- / sizeof (__ucs4_to_ibm937sb[0])), 0) \
- || (cp = __ucs4_to_ibm937sb[ch], \
- __builtin_expect (cp[0], '\1') == '\0' && ch != 0)) \
+ if (__builtin_expect (ch >= 0xffff, 0)) \
{ \
- /* Use the UCS4 table for double byte. */ \
- cp = __ucs4_to_ibm937db[ch]; \
- if (__builtin_expect (ch >= (sizeof (__ucs4_to_ibm937db) \
- / sizeof (__ucs4_to_ibm937db[0])), 0) \
- || __builtin_expect (cp[0], '\1') == '\0') \
+ UNICODE_TAG_HANDLER (ch, 4); \
+ \
+ if (! ignore_errors_p ()) \
{ \
- UNICODE_TAG_HANDLER (ch, 4); \
+ result = __GCONV_ILLEGAL_INPUT; \
+ break; \
+ } \
+ ++*irreversible; \
+ inptr += 4; \
+ continue; \
+ } \
\
+ while (ch > rp1->end) \
+ ++rp1; \
+ \
+ /* Use the UCS4 table for single byte. */ \
+ if (__builtin_expect (ch < rp1->start, 0) \
+ || (cp = __ucs4_to_ibm937sb[ch + rp1->idx], \
+ __builtin_expect (cp[0], L'\1') == L'\0' && ch != '\0')) \
+ { \
+ /* Use the UCS4 table for double byte. */ \
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+ if (__builtin_expect (ch < rp2->start, 0) \
+ || (cp = __ucs4_to_ibm937db[ch + rp2->idx], \
+ __builtin_expect (cp[0], L'\1')==L'\0' && ch != '\0')) \
+ { \
/* This is an illegal character. */ \
if (! ignore_errors_p ()) \
{ \
@@ -209,10 +243,16 @@ enum
{ \
if (curcs == sb) \
{ \
+ if (__builtin_expect (outptr + 1 > outend, 0)) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
*outptr++ = SO; \
curcs = db; \
} \
- if (__builtin_expect (outptr + 1 >= outend, 0)) \
+ \
+ if (__builtin_expect (outptr + 2 > outend, 0)) \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
@@ -225,15 +265,21 @@ enum
{ \
if (curcs == db) \
{ \
- *outptr++ = SI; \
- curcs = sb; \
- if (__builtin_expect (outptr == outend, 0)) \
+ if (__builtin_expect (outptr + 1 > outend, 0)) \
{ \
result = __GCONV_FULL_OUTPUT; \
break; \
} \
+ *outptr++ = SI; \
+ } \
+ \
+ if (__builtin_expect (outptr + 1 > outend, 0)) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
} \
*outptr++ = cp[0]; \
+ curcs = sb; \
} \
\
/* Now that we wrote the output increment the input pointer. */ \