X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fsiconv.c;h=8557bbd301ecc4dafb6cc6c43a8b38ebae06bbab;hb=cccb7ecd623450d5b3ca2391327788c84aed71c8;hp=26f36780d449a36e9223abe6b79ed5ce4c4df4a5;hpb=d38ee71c31b49ad13164039140ed47d18e9432cb;p=yaz-moved-to-github.git diff --git a/src/siconv.c b/src/siconv.c index 26f3678..8557bbd 100644 --- a/src/siconv.c +++ b/src/siconv.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1995-2007, Index Data ApS + * Copyright (C) 1995-2008, Index Data ApS * See the file LICENSE for details. * - * $Id: siconv.c,v 1.37 2007-03-20 21:37:32 adam Exp $ + * $Id: siconv.c,v 1.50 2008-03-12 08:53:28 adam Exp $ */ /** * \file siconv.c @@ -33,47 +33,61 @@ #include #endif +#include +#include +#include "iconv-p.h" -#include -unsigned long yaz_marc8_1_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_42_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_2_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_45_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_3_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_67_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_4_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_62_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_5_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_70_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_6_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_32_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_7_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_4E_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_8_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_51_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8_9_conv(unsigned char *inp, size_t inbytesleft, +unsigned long yaz_marc8_33_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8_34_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8_53_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8_31_conv(unsigned char *inp, size_t inbytesleft, size_t *no_read, int *combining); -unsigned long yaz_marc8r_1_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_2_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_3_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_4_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_5_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_6_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_7_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_8_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); -unsigned long yaz_marc8r_9_conv(unsigned char *inp, size_t inbytesleft, - size_t *no_read, int *combining); +unsigned long yaz_marc8r_42_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_45_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_67_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_62_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_70_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_32_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_4E_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_51_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_33_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_34_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_53_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); +unsigned long yaz_marc8r_31_conv(unsigned char *inp, size_t inbytesleft, + size_t *no_read, int *combining); struct yaz_iconv_struct { int my_errno; @@ -86,7 +100,8 @@ struct yaz_iconv_struct { char **outbuf, size_t *outbytesleft); size_t (*flush_handle)(yaz_iconv_t cd, char **outbuf, size_t *outbytesleft); - int marc8_esc_mode; + int g0_mode; + int g1_mode; int comb_offset; int comb_size; @@ -99,13 +114,14 @@ struct yaz_iconv_struct { #endif unsigned long compose_char; - unsigned long write_marc8_comb_ch[8]; - size_t write_marc8_comb_no; unsigned write_marc8_second_half_char; unsigned long write_marc8_last; - const char *write_marc8_page_chr; + const char *write_marc8_lpage; + const char *write_marc8_g0; + const char *write_marc8_g1; }; + static struct { unsigned long x1, x2; unsigned y; @@ -177,161 +193,21 @@ static struct { { 0, 0, 0} }; -static unsigned long yaz_read_ISO8859_1 (yaz_iconv_t cd, unsigned char *inp, - size_t inbytesleft, size_t *no_read) -{ - unsigned long x = inp[0]; - *no_read = 1; - return x; -} +#define ESC "\033" +static size_t yaz_write_marc8_page_chr(yaz_iconv_t cd, + char **outbuf, size_t *outbytesleft, + const char *page_chr); -static size_t yaz_init_UTF8 (yaz_iconv_t cd, unsigned char *inp, - size_t inbytesleft, size_t *no_read) -{ - if (inp[0] != 0xef) - { - *no_read = 0; - return 0; - } - if (inbytesleft < 3) - { - cd->my_errno = YAZ_ICONV_EINVAL; - return (size_t) -1; - } - if (inp[1] != 0xbb && inp[2] == 0xbf) - *no_read = 3; - else - *no_read = 0; - return 0; -} - -unsigned long yaz_read_UTF8_char(unsigned char *inp, - size_t inbytesleft, size_t *no_read, - int *error) +static unsigned long yaz_read_ISO8859_1(yaz_iconv_t cd, unsigned char *inp, + size_t inbytesleft, size_t *no_read) { - unsigned long x = 0; - - if (inp[0] <= 0x7f) - { - x = inp[0]; - *no_read = 1; - } - else if (inp[0] <= 0xbf || inp[0] >= 0xfe) - { - *no_read = 0; - *error = YAZ_ICONV_EILSEQ; - } - else if (inp[0] <= 0xdf && inbytesleft >= 2) - { - x = ((inp[0] & 0x1f) << 6) | (inp[1] & 0x3f); - if (x >= 0x80) - *no_read = 2; - else - { - *no_read = 0; - *error = YAZ_ICONV_EILSEQ; - } - } - else if (inp[0] <= 0xef && inbytesleft >= 3) - { - x = ((inp[0] & 0x0f) << 12) | ((inp[1] & 0x3f) << 6) | - (inp[2] & 0x3f); - if (x >= 0x800) - *no_read = 3; - else - { - *no_read = 0; - *error = YAZ_ICONV_EILSEQ; - } - } - else if (inp[0] <= 0xf7 && inbytesleft >= 4) - { - x = ((inp[0] & 0x07) << 18) | ((inp[1] & 0x3f) << 12) | - ((inp[2] & 0x3f) << 6) | (inp[3] & 0x3f); - if (x >= 0x10000) - *no_read = 4; - else - { - *no_read = 0; - *error = YAZ_ICONV_EILSEQ; - } - } - else if (inp[0] <= 0xfb && inbytesleft >= 5) - { - x = ((inp[0] & 0x03) << 24) | ((inp[1] & 0x3f) << 18) | - ((inp[2] & 0x3f) << 12) | ((inp[3] & 0x3f) << 6) | - (inp[4] & 0x3f); - if (x >= 0x200000) - *no_read = 5; - else - { - *no_read = 0; - *error = YAZ_ICONV_EILSEQ; - } - } - else if (inp[0] <= 0xfd && inbytesleft >= 6) - { - x = ((inp[0] & 0x01) << 30) | ((inp[1] & 0x3f) << 24) | - ((inp[2] & 0x3f) << 18) | ((inp[3] & 0x3f) << 12) | - ((inp[4] & 0x3f) << 6) | (inp[5] & 0x3f); - if (x >= 0x4000000) - *no_read = 6; - else - { - *no_read = 0; - *error = YAZ_ICONV_EILSEQ; - } - } - else - { - *no_read = 0; - *error = YAZ_ICONV_EINVAL; - } + unsigned long x = inp[0]; + *no_read = 1; return x; } -static unsigned long yaz_read_UTF8 (yaz_iconv_t cd, unsigned char *inp, - size_t inbytesleft, size_t *no_read) -{ - return yaz_read_UTF8_char(inp, inbytesleft, no_read, &cd->my_errno); -} -static unsigned long yaz_read_UCS4 (yaz_iconv_t cd, unsigned char *inp, - size_t inbytesleft, size_t *no_read) -{ - unsigned long x = 0; - - if (inbytesleft < 4) - { - cd->my_errno = YAZ_ICONV_EINVAL; /* incomplete input */ - *no_read = 0; - } - else - { - x = (inp[0]<<24) | (inp[1]<<16) | (inp[2]<<8) | inp[3]; - *no_read = 4; - } - return x; -} - -static unsigned long yaz_read_UCS4LE (yaz_iconv_t cd, unsigned char *inp, - size_t inbytesleft, size_t *no_read) -{ - unsigned long x = 0; - - if (inbytesleft < 4) - { - cd->my_errno = YAZ_ICONV_EINVAL; /* incomplete input */ - *no_read = 0; - } - else - { - x = (inp[3]<<24) | (inp[2]<<16) | (inp[1]<<8) | inp[0]; - *no_read = 4; - } - return x; -} #if HAVE_WCHAR_H static unsigned long yaz_read_wchar_t (yaz_iconv_t cd, unsigned char *inp, @@ -355,360 +231,6 @@ static unsigned long yaz_read_wchar_t (yaz_iconv_t cd, unsigned char *inp, } #endif -static unsigned long yaz_read_advancegreek(yaz_iconv_t cd, unsigned char *inp, - size_t inbytesleft, size_t *no_read) -{ - unsigned long x = 0; - int shift = 0; - int tonos = 0; - int dialitika = 0; - - *no_read = 0; - while (inbytesleft > 0) - { - if (*inp == 0x9d) - { - tonos = 1; - } - else if (*inp == 0x9e) - { - dialitika = 1; - } - else if (*inp == 0x9f) - { - shift = 1; - } - else - break; - inp++; - --inbytesleft; - (*no_read)++; - } - if (inbytesleft == 0) - { - cd->my_errno = YAZ_ICONV_EINVAL; /* incomplete input */ - *no_read = 0; - return 0; - } - switch (*inp) { - case 0x81: - if (shift) - if (tonos) - x = 0x0386; - else - x = 0x0391; - else - if (tonos) - x = 0x03ac; - else - x = 0x03b1; - break; - case 0x82: - if (shift) - x = 0x0392; - else - x = 0x03b2; - - break; - case 0x83: - if (shift) - x = 0x0393; - else - x = 0x03b3; - break; - case 0x84: - if (shift) - x = 0x0394; - else - x = 0x03b4; - break; - case 0x85: - if (shift) - if (tonos) - x = 0x0388; - else - x = 0x0395; - else - if (tonos) - x = 0x03ad; - else - x = 0x03b5; - break; - case 0x86: - if (shift) - x = 0x0396; - else - x = 0x03b6; - break; - case 0x87: - if (shift) - if (tonos) - x = 0x0389; - else - x = 0x0397; - else - if (tonos) - x = 0x03ae; - else - x = 0x03b7; - break; - case 0x88: - if (shift) - x = 0x0398; - else - x = 0x03b8; - break; - case 0x89: - if (shift) - if (tonos) - x = 0x038a; - else - if (dialitika) - x = 0x9e; - else - x = 0x0399; - else - if (tonos) - if (dialitika) - x = 0x0390; - else - x = 0x03af; - - else - if (dialitika) - x = 0x03ca; - else - x = 0x03b9; - break; - case 0x8a: - if (shift) - x = 0x039a; - else - x = 0x03ba; - - break; - case 0x8b: - if (shift) - x = 0x039b; - else - x = 0x03bb; - break; - case 0x8c: - if (shift) - x = 0x039c; - else - x = 0x03bc; - - break; - case 0x8d: - if (shift) - x = 0x039d; - else - x = 0x03bd; - break; - case 0x8e: - if (shift) - x = 0x039e; - else - x = 0x03be; - break; - case 0x8f: - if (shift) - if (tonos) - x = 0x038c; - else - x = 0x039f; - else - if (tonos) - x = 0x03cc; - else - x = 0x03bf; - break; - case 0x90: - if (shift) - x = 0x03a0; - else - x = 0x03c0; - break; - case 0x91: - if (shift) - x = 0x03a1; - else - x = 0x03c1; - break; - case 0x92: - x = 0x03c2; - break; - case 0x93: - if (shift) - x = 0x03a3; - else - x = 0x03c3; - break; - case 0x94: - if (shift) - x = 0x03a4; - else - x = 0x03c4; - break; - case 0x95: - if (shift) - if (tonos) - x = 0x038e; - else - if (dialitika) - x = 0x03ab; - else - x = 0x03a5; - else - if (tonos) - if (dialitika) - x = 0x03b0; - else - x = 0x03cd; - - else - if (dialitika) - x = 0x03cb; - else - x = 0x03c5; - break; - case 0x96: - if (shift) - x = 0x03a6; - else - x = 0x03c6; - break; - case 0x97: - if (shift) - x = 0x03a7; - else - x = 0x03c7; - break; - case 0x98: - if (shift) - x = 0x03a8; - else - x = 0x03c8; - - break; - - case 0x99: - if (shift) - if (tonos) - x = 0x038f; - else - x = 0x03a9; - else - if (tonos) - x = 0x03ce; - else - x = 0x03c9; - break; - default: - x = *inp; - break; - } - (*no_read)++; - - return x; -} - -static size_t yaz_write_advancegreek(yaz_iconv_t cd, unsigned long x, - char **outbuf, size_t *outbytesleft) -{ - size_t k = 0; - unsigned char *out = (unsigned char*) *outbuf; - if (*outbytesleft < 3) - { - cd->my_errno = YAZ_ICONV_E2BIG; /* not room for output */ - return (size_t)(-1); - } - switch (x) - { - case 0x03ac : out[k++]=0x9d; out[k++]=0x81; break; - case 0x03ad : out[k++]=0x9d; out[k++]=0x85; break; - case 0x03ae : out[k++]=0x9d; out[k++]=0x87; break; - case 0x03af : out[k++]=0x9d; out[k++]=0x89; break; - case 0x03cc : out[k++]=0x9d; out[k++]=0x8f; break; - case 0x03cd : out[k++]=0x9d; out[k++]=0x95; break; - case 0x03ce : out[k++]=0x9d; out[k++]=0x99; break; - case 0x0390 : out[k++]=0x9d; out[k++]=0x9e; out[k++]=0x89; break; - case 0x03b0 : out[k++]=0x9d; out[k++]=0x9e; out[k++]=0x95; break; - case 0x0386 : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x81; break; - case 0x0388 : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x85; break; - case 0x0389 : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x87; break; - case 0x038a : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x89; break; - case 0x038c : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x8f; break; - case 0x038e : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x95; break; - case 0x038f : out[k++]=0x9d; out[k++]=0x9f; out[k++]=0x99; break; - case 0x03ca : out[k++]=0x9e; out[k++]=0x89; break; - case 0x03cb : out[k++]=0x9e; out[k++]=0x95; break; - case 0x03aa : out[k++]=0x9e; out[k++]=0x9f; out[k++]=0x89; break; - case 0x03ab : out[k++]=0x9e; out[k++]=0x9f; out[k++]=0x95; break; - case 0x0391 : out[k++]=0x9f; out[k++]=0x81; break; - case 0x0392 : out[k++]=0x9f; out[k++]=0x82; break; - case 0x0393 : out[k++]=0x9f; out[k++]=0x83; break; - case 0x0394 : out[k++]=0x9f; out[k++]=0x84; break; - case 0x0395 : out[k++]=0x9f; out[k++]=0x85; break; - case 0x0396 : out[k++]=0x9f; out[k++]=0x86; break; - case 0x0397 : out[k++]=0x9f; out[k++]=0x87; break; - case 0x0398 : out[k++]=0x9f; out[k++]=0x88; break; - case 0x0399 : out[k++]=0x9f; out[k++]=0x89; break; - case 0x039a : out[k++]=0x9f; out[k++]=0x8a; break; - case 0x039b : out[k++]=0x9f; out[k++]=0x8b; break; - case 0x039c : out[k++]=0x9f; out[k++]=0x8c; break; - case 0x039d : out[k++]=0x9f; out[k++]=0x8d; break; - case 0x039e : out[k++]=0x9f; out[k++]=0x8e; break; - case 0x039f : out[k++]=0x9f; out[k++]=0x8f; break; - case 0x03a0 : out[k++]=0x9f; out[k++]=0x90; break; - case 0x03a1 : out[k++]=0x9f; out[k++]=0x91; break; - case 0x03a3 : out[k++]=0x9f; out[k++]=0x93; break; - case 0x03a4 : out[k++]=0x9f; out[k++]=0x94; break; - case 0x03a5 : out[k++]=0x9f; out[k++]=0x95; break; - case 0x03a6 : out[k++]=0x9f; out[k++]=0x96; break; - case 0x03a7 : out[k++]=0x9f; out[k++]=0x97; break; - case 0x03a8 : out[k++]=0x9f; out[k++]=0x98; break; - case 0x03a9 : out[k++]=0x9f; out[k++]=0x99; break; - case 0x03b1 : out[k++]=0x81; break; - case 0x03b2 : out[k++]=0x82; break; - case 0x03b3 : out[k++]=0x83; break; - case 0x03b4 : out[k++]=0x84; break; - case 0x03b5 : out[k++]=0x85; break; - case 0x03b6 : out[k++]=0x86; break; - case 0x03b7 : out[k++]=0x87; break; - case 0x03b8 : out[k++]=0x88; break; - case 0x03b9 : out[k++]=0x89; break; - case 0x03ba : out[k++]=0x8a; break; - case 0x03bb : out[k++]=0x8b; break; - case 0x03bc : out[k++]=0x8c; break; - case 0x03bd : out[k++]=0x8d; break; - case 0x03be : out[k++]=0x8e; break; - case 0x03bf : out[k++]=0x8f; break; - case 0x03c0 : out[k++]=0x90; break; - case 0x03c1 : out[k++]=0x91; break; - case 0x03c2 : out[k++]=0x92; break; - case 0x03c3 : out[k++]=0x93; break; - case 0x03c4 : out[k++]=0x94; break; - case 0x03c5 : out[k++]=0x95; break; - case 0x03c6 : out[k++]=0x96; break; - case 0x03c7 : out[k++]=0x96; break; - case 0x03c8 : out[k++]=0x98; break; - case 0x03c9 : out[k++]=0x99; break; - default: - if (x > 255) - { - cd->my_errno = YAZ_ICONV_EILSEQ; - return (size_t) -1; - } - out[k++] = x; - break; - } - *outbytesleft -= k; - (*outbuf) += k; - return 0; -} - static unsigned long yaz_read_marc8_comb (yaz_iconv_t cd, unsigned char *inp, size_t inbytesleft, size_t *no_read, @@ -791,66 +313,102 @@ static unsigned long yaz_read_marc8_comb(yaz_iconv_t cd, unsigned char *inp, int *comb) { *no_read = 0; - while(inbytesleft >= 1 && inp[0] == 27) + while (inbytesleft > 0 && *inp == 27) { + int *modep = &cd->g0_mode; size_t inbytesleft0 = inbytesleft; - inp++; + inbytesleft--; - while(inbytesleft > 0 && strchr("(,$!)-", *inp)) + inp++; + if (inbytesleft == 0) + goto incomplete; + if (*inp == '$') /* set with multiple bytes */ { inbytesleft--; inp++; } - if (inbytesleft <= 0) + if (inbytesleft == 0) + goto incomplete; + if (*inp == '(' || *inp == ',') /* G0 */ { - *no_read = 0; - cd->my_errno = YAZ_ICONV_EINVAL; - return 0; + inbytesleft--; + inp++; } - cd->marc8_esc_mode = *inp++; + else if (*inp == ')' || *inp == '-') /* G1 */ + { + inbytesleft--; + inp++; + modep = &cd->g1_mode; + } + if (inbytesleft == 0) + goto incomplete; + if (*inp == '!') /* ANSEL is a special case */ + { + inbytesleft--; + inp++; + } + if (inbytesleft == 0) + goto incomplete; + *modep = *inp++; /* Final character */ inbytesleft--; + (*no_read) += inbytesleft0 - inbytesleft; } - if (inbytesleft <= 0) + if (inbytesleft == 0) return 0; + else if (*inp == ' ') + { + *no_read += 1; + return ' '; + } else { unsigned long x; size_t no_read_sub = 0; + int mode = *inp < 128 ? cd->g0_mode : cd->g1_mode; *comb = 0; - switch(cd->marc8_esc_mode) + switch(mode) { case 'B': /* Basic ASCII */ - case 'E': /* ANSEL */ case 's': /* ASCII */ - x = yaz_marc8_1_conv(inp, inbytesleft, &no_read_sub, comb); + case 'E': /* ANSEL */ + x = yaz_marc8_42_conv(inp, inbytesleft, &no_read_sub, comb); + if (!x) + { + no_read_sub = 0; + x = yaz_marc8_45_conv(inp, inbytesleft, &no_read_sub, comb); + } break; case 'g': /* Greek */ - x = yaz_marc8_2_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_67_conv(inp, inbytesleft, &no_read_sub, comb); break; case 'b': /* Subscripts */ - x = yaz_marc8_3_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_62_conv(inp, inbytesleft, &no_read_sub, comb); break; case 'p': /* Superscripts */ - x = yaz_marc8_4_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_70_conv(inp, inbytesleft, &no_read_sub, comb); break; case '2': /* Basic Hebrew */ - x = yaz_marc8_5_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_32_conv(inp, inbytesleft, &no_read_sub, comb); break; case 'N': /* Basic Cyrillic */ + x = yaz_marc8_4E_conv(inp, inbytesleft, &no_read_sub, comb); + break; case 'Q': /* Extended Cyrillic */ - x = yaz_marc8_6_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_51_conv(inp, inbytesleft, &no_read_sub, comb); break; case '3': /* Basic Arabic */ + x = yaz_marc8_33_conv(inp, inbytesleft, &no_read_sub, comb); + break; case '4': /* Extended Arabic */ - x = yaz_marc8_7_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_34_conv(inp, inbytesleft, &no_read_sub, comb); break; case 'S': /* Greek */ - x = yaz_marc8_8_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_53_conv(inp, inbytesleft, &no_read_sub, comb); break; case '1': /* Chinese, Japanese, Korean (EACC) */ - x = yaz_marc8_9_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8_31_conv(inp, inbytesleft, &no_read_sub, comb); break; default: *no_read = 0; @@ -860,76 +418,14 @@ static unsigned long yaz_read_marc8_comb(yaz_iconv_t cd, unsigned char *inp, *no_read += no_read_sub; return x; } -} - -static size_t yaz_write_UTF8(yaz_iconv_t cd, unsigned long x, - char **outbuf, size_t *outbytesleft) -{ - return yaz_write_UTF8_char(x, outbuf, outbytesleft, &cd->my_errno); -} - -size_t yaz_write_UTF8_char(unsigned long x, - char **outbuf, size_t *outbytesleft, - int *error) -{ - unsigned char *outp = (unsigned char *) *outbuf; - - if (x <= 0x7f && *outbytesleft >= 1) - { - *outp++ = (unsigned char) x; - (*outbytesleft)--; - } - else if (x <= 0x7ff && *outbytesleft >= 2) - { - *outp++ = (unsigned char) ((x >> 6) | 0xc0); - *outp++ = (unsigned char) ((x & 0x3f) | 0x80); - (*outbytesleft) -= 2; - } - else if (x <= 0xffff && *outbytesleft >= 3) - { - *outp++ = (unsigned char) ((x >> 12) | 0xe0); - *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80); - *outp++ = (unsigned char) ((x & 0x3f) | 0x80); - (*outbytesleft) -= 3; - } - else if (x <= 0x1fffff && *outbytesleft >= 4) - { - *outp++ = (unsigned char) ((x >> 18) | 0xf0); - *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80); - *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80); - *outp++ = (unsigned char) ((x & 0x3f) | 0x80); - (*outbytesleft) -= 4; - } - else if (x <= 0x3ffffff && *outbytesleft >= 5) - { - *outp++ = (unsigned char) ((x >> 24) | 0xf8); - *outp++ = (unsigned char) (((x >> 18) & 0x3f) | 0x80); - *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80); - *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80); - *outp++ = (unsigned char) ((x & 0x3f) | 0x80); - (*outbytesleft) -= 5; - } - else if (*outbytesleft >= 6) - { - *outp++ = (unsigned char) ((x >> 30) | 0xfc); - *outp++ = (unsigned char) (((x >> 24) & 0x3f) | 0x80); - *outp++ = (unsigned char) (((x >> 18) & 0x3f) | 0x80); - *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80); - *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80); - *outp++ = (unsigned char) ((x & 0x3f) | 0x80); - (*outbytesleft) -= 6; - } - else - { - *error = YAZ_ICONV_E2BIG; /* not room for output */ - return (size_t)(-1); - } - *outbuf = (char *) outp; +incomplete: + *no_read = 0; + cd->my_errno = YAZ_ICONV_EINVAL; return 0; } -static size_t yaz_write_ISO8859_1 (yaz_iconv_t cd, unsigned long x, - char **outbuf, size_t *outbytesleft) +static size_t yaz_write_ISO8859_1(yaz_iconv_t cd, unsigned long x, + char **outbuf, size_t *outbytesleft) { /* list of two char unicode sequence that, when combined, are equivalent to single unicode chars that can be represented in @@ -1004,48 +500,6 @@ static size_t yaz_flush_ISO8859_1(yaz_iconv_t cd, return 0; } -static size_t yaz_write_UCS4 (yaz_iconv_t cd, unsigned long x, - char **outbuf, size_t *outbytesleft) -{ - unsigned char *outp = (unsigned char *) *outbuf; - if (*outbytesleft >= 4) - { - *outp++ = (unsigned char) (x>>24); - *outp++ = (unsigned char) (x>>16); - *outp++ = (unsigned char) (x>>8); - *outp++ = (unsigned char) x; - (*outbytesleft) -= 4; - } - else - { - cd->my_errno = YAZ_ICONV_E2BIG; - return (size_t)(-1); - } - *outbuf = (char *) outp; - return 0; -} - -static size_t yaz_write_UCS4LE (yaz_iconv_t cd, unsigned long x, - char **outbuf, size_t *outbytesleft) -{ - unsigned char *outp = (unsigned char *) *outbuf; - if (*outbytesleft >= 4) - { - *outp++ = (unsigned char) x; - *outp++ = (unsigned char) (x>>8); - *outp++ = (unsigned char) (x>>16); - *outp++ = (unsigned char) (x>>24); - (*outbytesleft) -= 4; - } - else - { - cd->my_errno = YAZ_ICONV_E2BIG; - return (size_t)(-1); - } - *outbuf = (char *) outp; - return 0; -} - static unsigned long lookup_marc8(yaz_iconv_t cd, unsigned long x, int *comb, const char **page_chr) @@ -1069,59 +523,71 @@ static unsigned long lookup_marc8(yaz_iconv_t cd, *utf8_outbuf = '\0'; inp = (unsigned char *) utf8_buf; inbytesleft = strlen(utf8_buf); - - x = yaz_marc8r_1_conv(inp, inbytesleft, &no_read_sub, comb); + + x = yaz_marc8r_42_conv(inp, inbytesleft, &no_read_sub, comb); + if (x) + { + *page_chr = ESC "(B"; + return x; + } + x = yaz_marc8r_45_conv(inp, inbytesleft, &no_read_sub, comb); + if (x) + { + *page_chr = ESC "(B"; + return x; + } + x = yaz_marc8r_62_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033(B"; + *page_chr = ESC "b"; return x; } - x = yaz_marc8r_2_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_70_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033g"; + *page_chr = ESC "p"; return x; } - x = yaz_marc8r_3_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_32_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033b"; + *page_chr = ESC "(2"; return x; } - x = yaz_marc8r_4_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_4E_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033p"; + *page_chr = ESC "(N"; return x; } - x = yaz_marc8r_5_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_51_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033(2"; + *page_chr = ESC "(Q"; return x; } - x = yaz_marc8r_6_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_33_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033(N"; + *page_chr = ESC "(3"; return x; } - x = yaz_marc8r_7_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_34_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033(3"; + *page_chr = ESC "(4"; return x; } - x = yaz_marc8r_8_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_53_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033(S"; + *page_chr = ESC "(S"; return x; } - x = yaz_marc8r_9_conv(inp, inbytesleft, &no_read_sub, comb); + x = yaz_marc8r_31_conv(inp, inbytesleft, &no_read_sub, comb); if (x) { - *page_chr = "\033$1"; + *page_chr = ESC "$1"; return x; } cd->my_errno = YAZ_ICONV_EILSEQ; @@ -1134,12 +600,21 @@ static size_t flush_combos(yaz_iconv_t cd, { unsigned long y = cd->write_marc8_last; unsigned char byte; - char out_buf[10]; - size_t i, out_no = 0; + char out_buf[4]; + size_t out_no = 0; if (!y) return 0; + assert(cd->write_marc8_lpage); + if (cd->write_marc8_lpage) + { + size_t r = yaz_write_marc8_page_chr(cd, outbuf, outbytesleft, + cd->write_marc8_lpage); + if (r) + return r; + } + byte = (unsigned char )((y>>16) & 0xff); if (byte) out_buf[out_no++] = byte; @@ -1150,19 +625,12 @@ static size_t flush_combos(yaz_iconv_t cd, if (byte) out_buf[out_no++] = byte; - if (out_no + cd->write_marc8_comb_no + 1 > *outbytesleft) + if (out_no + 2 >= *outbytesleft) { cd->my_errno = YAZ_ICONV_E2BIG; return (size_t) (-1); } - for (i = 0; i < cd->write_marc8_comb_no; i++) - { - /* all MARC-8 combined characters are simple bytes */ - byte = (unsigned char )(cd->write_marc8_comb_ch[i]); - *(*outbuf)++ = byte; - (*outbytesleft)--; - } memcpy(*outbuf, out_buf, out_no); *outbuf += out_no; (*outbytesleft) -= out_no; @@ -1173,7 +641,7 @@ static size_t flush_combos(yaz_iconv_t cd, } cd->write_marc8_last = 0; - cd->write_marc8_comb_no = 0; + cd->write_marc8_lpage = 0; cd->write_marc8_second_half_char = 0; return 0; } @@ -1182,8 +650,13 @@ static size_t yaz_write_marc8_page_chr(yaz_iconv_t cd, char **outbuf, size_t *outbytesleft, const char *page_chr) { - const char *old_page_chr = cd->write_marc8_page_chr; - if (strcmp(page_chr, old_page_chr)) + const char **old_page_chr = &cd->write_marc8_g0; + + /* are we going to a G1-set (such as such as ESC ")!E") */ + if (page_chr && page_chr[1] == ')') + old_page_chr = &cd->write_marc8_g1; + + if (!*old_page_chr || strcmp(page_chr, *old_page_chr)) { size_t plen = 0; const char *page_out = page_chr; @@ -1194,24 +667,27 @@ static size_t yaz_write_marc8_page_chr(yaz_iconv_t cd, return (size_t) (-1); } - cd->write_marc8_page_chr = page_chr; - - if (!strcmp(old_page_chr, "\033p") - || !strcmp(old_page_chr, "\033g") - || !strcmp(old_page_chr, "\033b")) + + if (*old_page_chr) { - /* Technique 1 leave */ - page_out = "\033s"; - if (strcmp(page_chr, "\033(B")) /* Not going ASCII page? */ + if (!strcmp(*old_page_chr, ESC "p") + || !strcmp(*old_page_chr, ESC "g") + || !strcmp(*old_page_chr, ESC "b")) { - /* Must leave script + enter new page */ - plen = strlen(page_out); - memcpy(*outbuf, page_out, plen); - (*outbuf) += plen; - (*outbytesleft) -= plen; - page_out = page_chr; + page_out = ESC "s"; + /* Technique 1 leave */ + if (strcmp(page_chr, ESC "(B")) /* Not going ASCII page? */ + { + /* Must leave script + enter new page */ + plen = strlen(page_out); + memcpy(*outbuf, page_out, plen); + (*outbuf) += plen; + (*outbytesleft) -= plen; + page_out = ESC "(B"; + } } } + *old_page_chr = page_chr; plen = strlen(page_out); memcpy(*outbuf, page_out, plen); (*outbuf) += plen; @@ -1233,13 +709,25 @@ static size_t yaz_write_marc8_2(yaz_iconv_t cd, unsigned long x, if (comb) { + if (page_chr) + { + size_t r = yaz_write_marc8_page_chr(cd, outbuf, outbytesleft, + page_chr); + if (r) + return r; + } if (x == 0x0361) cd->write_marc8_second_half_char = 0xEC; else if (x == 0x0360) cd->write_marc8_second_half_char = 0xFB; - if (cd->write_marc8_comb_no < 6) - cd->write_marc8_comb_ch[cd->write_marc8_comb_no++] = y; + if (*outbytesleft <= 1) + { + cd->my_errno = YAZ_ICONV_E2BIG; + return (size_t) (-1); + } + *(*outbuf)++ = y; + (*outbytesleft)--; } else { @@ -1247,10 +735,8 @@ static size_t yaz_write_marc8_2(yaz_iconv_t cd, unsigned long x, if (r) return r; - r = yaz_write_marc8_page_chr(cd, outbuf, outbytesleft, page_chr); - if (r) - return r; cd->write_marc8_last = y; + cd->write_marc8_lpage = page_chr; } return 0; } @@ -1261,7 +747,8 @@ static size_t yaz_flush_marc8(yaz_iconv_t cd, size_t r = flush_combos(cd, outbuf, outbytesleft); if (r) return r; - return yaz_write_marc8_page_chr(cd, outbuf, outbytesleft, "\033(B"); + cd->write_marc8_g1 = 0; + return yaz_write_marc8_page_chr(cd, outbuf, outbytesleft, ESC "(B"); } static size_t yaz_write_marc8(yaz_iconv_t cd, unsigned long x, @@ -1277,6 +764,7 @@ static size_t yaz_write_marc8(yaz_iconv_t cd, unsigned long x, char *outbuf0 = *outbuf; size_t outbytesleft0 = *outbytesleft; int last_ch = cd->write_marc8_last; + const char *lpage = cd->write_marc8_lpage; r = yaz_write_marc8_2(cd, latin1_comb[i].x1, outbuf, outbytesleft); @@ -1290,6 +778,7 @@ static size_t yaz_write_marc8(yaz_iconv_t cd, unsigned long x, *outbuf = outbuf0; *outbytesleft = outbytesleft0; cd->write_marc8_last = last_ch; + cd->write_marc8_lpage = lpage; } return r; } @@ -1359,6 +848,10 @@ yaz_iconv_t yaz_iconv_open (const char *tocode, const char *fromcode) cd->read_handle = yaz_read_marc8s; else if (!yaz_matchstr(fromcode, "advancegreek")) cd->read_handle = yaz_read_advancegreek; + else if (!yaz_matchstr(fromcode, "iso54281984")) + cd->read_handle = yaz_read_iso5428_1984; + else if (!yaz_matchstr(fromcode, "iso5428:1984")) + cd->read_handle = yaz_read_iso5428_1984; #if HAVE_WCHAR_H else if (!yaz_matchstr(fromcode, "WCHAR_T")) cd->read_handle = yaz_read_wchar_t; @@ -1389,6 +882,14 @@ yaz_iconv_t yaz_iconv_open (const char *tocode, const char *fromcode) { cd->write_handle = yaz_write_advancegreek; } + else if (!yaz_matchstr(tocode, "iso54281984")) + { + cd->write_handle = yaz_write_iso5428_1984; + } + else if (!yaz_matchstr(tocode, "iso5428:1984")) + { + cd->write_handle = yaz_write_iso5428_1984; + } #if HAVE_WCHAR_H else if (!yaz_matchstr(tocode, "WCHAR_T")) cd->write_handle = yaz_write_wchar_t; @@ -1454,15 +955,17 @@ size_t yaz_iconv(yaz_iconv_t cd, char **inbuf, size_t *inbytesleft, if (cd->init_flag) { cd->my_errno = YAZ_ICONV_UNKNOWN; - cd->marc8_esc_mode = 'B'; + cd->g0_mode = 'B'; + cd->g1_mode = 'B'; cd->comb_offset = cd->comb_size = 0; cd->compose_char = 0; - cd->write_marc8_comb_no = 0; cd->write_marc8_second_half_char = 0; cd->write_marc8_last = 0; - cd->write_marc8_page_chr = "\033(B"; + cd->write_marc8_lpage = 0; + cd->write_marc8_g0 = ESC "(B"; + cd->write_marc8_g1 = 0; cd->unget_x = 0; cd->no_read_x = 0; @@ -1564,6 +1067,11 @@ int yaz_iconv_close (yaz_iconv_t cd) return 0; } +void yaz_iconv_set_errno(yaz_iconv_t cd, int no) +{ + cd->my_errno = no; +} + /* * Local variables: * c-basic-offset: 4 @@ -1571,4 +1079,3 @@ int yaz_iconv_close (yaz_iconv_t cd) * End: * vim: shiftwidth=4 tabstop=8 expandtab */ -