diff options
141 files changed, 4524 insertions, 5617 deletions
@@ -1,3 +1,241 @@ +1998-04-20 18:00 Ulrich Drepper <drepper@cygnus.com> + + * libc.map: Add __dgettext to GLIBC_2.0 and __libc_longjmp, and + __libc_siglongjmp to GLIBC_2.1. + + * elf/dl-minimal.c (__assert_perror_fail): Don't use strerror, use + __strerror_r. + + * iconv/Makefile: Don't run tests now. + + * iconv/iconv_prog.c (process_block): If loop is repeated, call iconv + with correct output buffer. + + Major rewrite of the low-level gconv functionality. + * iconv/gconv.c: Rewritten. + * iconv/gconv.h: Likewise. + * iconv/gconv_builtin.c: Likewise. + * iconv/gconv_builtin.h: Likewise. + * iconv/gconv_conf.c: Likewise. + * iconv/gconv_int.h: Likewise. + * iconv/gconv_open.c: Likewise. + * iconv/gconv_simple.c: Likewise. + * iconv/iconv.c: Likewise. + * iconvdata/8bit-gap.c: Likewise. + * iconvdata/8bit-generic.c: Likewise. + * iconvdata/Makefile: Likewise. + * iconvdata/big5.c: Likewise. + * iconvdata/cns11643.c: Likewise. + * iconvdata/cns11643.h: Likewise. + * iconvdata/cns11643l1.c: Likewise. + * iconvdata/cns11643l1.h: Likewise. + * iconvdata/ebcdic-at-de-a.c: Likewise. + * iconvdata/ebcdic-at-de.c: Likewise. + * iconvdata/ebcdic-ca-fr.c: Likewise. + * iconvdata/euccn.c: Likewise. + * iconvdata/eucjp.c: Likewise. + * iconvdata/euckr.c: Likewise. + * iconvdata/euctw.c: Likewise. + * iconvdata/gb2312.c: Likewise. + * iconvdata/gb2312.h: Likewise. + * iconvdata/hp-roman8.c: Likewise. + * iconvdata/iso646.c: Likewise. + * iconvdata/iso6937.c: Likewise. + * iconvdata/iso8859-1.c: Likewise. + * iconvdata/iso8859-10.c: Likewise. + * iconvdata/iso8859-2.c: Likewise. + * iconvdata/iso8859-3.c: Likewise. + * iconvdata/iso8859-4.c: Likewise. + * iconvdata/iso8859-5.c: Likewise. + * iconvdata/iso8859-6.c: Likewise. + * iconvdata/iso8859-7.c: Likewise. + * iconvdata/iso8859-8.c: Likewise. + * iconvdata/iso8859-9.c: Likewise. + * iconvdata/jis0201.c: Likewise. + * iconvdata/jis0201.h: Likewise. + * iconvdata/jis0208.c: Likewise. + * iconvdata/jis0208.h: Likewise. + * iconvdata/jis0212.c: Likewise. + * iconvdata/jis0212.h: Likewise. + * iconvdata/johab.c: Likewise. + * iconvdata/koi-8.c: Likewise. + * iconvdata/koi8-r.c: Likewise. + * iconvdata/ksc5601.c: Likewise. + * iconvdata/ksc5601.h: Likewise. + * iconvdata/latin-greek-1.c: Likewise. + * iconvdata/latin-greek.c: Likewise. + * iconvdata/run-iconv-test.sh: Likewise. + * iconvdata/sjis.c: Likewise. + * iconvdata/t61.c: Likewise. + * iconvdata/uhc.c: Likewise. + * wcsmbs/btowc.c: Likewise. + * wcsmbs/mbrtowc.c: Likewise. + * wcsmbs/mbsnrtowcs.c: Likewise. + * wcsmbs/mbsrtowcs.c: Likewise. + * wcsmbs/wcrtomb.c: Likewise. + * wcsmbs/wcsmbsload.c: Likewise. + * wcsmbs/wcsnrtombs.c: Likewise. + * wcsmbs/wcsrtombs.c: Likewise. + * wcsmbs/wctob.c: Likewise. + * iconv/loop.c: New file. + * iconv/skeleton.c: New file. + + * stdlib/mblen.c: Handle empty input string correctly. + * stdlib/mbtowc.c: Likewise. + + * posix/getopt.c: Various cleanups. + + * sysdeps/arm/bits/setjmp.h: Add copyright text. + * sysdeps/i386/bits/setjmp.h: Likewise. + * sysdeps/m68k/bits/setjmp.h: Likewise. + * sysdeps/powerpc/bits/setjmp.h: Likewise. + * sysdeps/sparc/sparc32/bits/setjmp.h: Likewise. + + * sysdeps/generic/longjmp.c: Rename function to __libc_siglongjmp + and make longjmp weak alias. + +1998-04-18 20:29 Philip Blundell <Philip.Blundell@pobox.com> + + * iconv/Makefile (routines): Only include gconv_dl if building for + an ELF system - dynamic linking is not available on a.out. + (CFLAGS-gconv_conf.c): Define STATIC_GCONV if omitting gconv_dl + due to above check. + * iconv/gconv_db.c: If STATIC_GCONV defined, don't try to call + routines from gconv_dl. + +1998-04-17 Gordon Matzigkeit <gord@profitpress.com> + + * csu/init.c (_IO_stdin_used): Protect with USE_IN_LIBIO so that + we can compile without libio. + +1998-04-20 16:28 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/mach/hurd/Subdirs: Remove login. + +1998-04-11 Gordon Matzigkeit <gord@profitpress.com> + + * db2/compat.h: Include <errno.h>, to make sure we get the + definition of EFTYPE before we define it ourselves. + +1998-04-10 Gordon Matzigkeit <gord@profitpress.com> + + * sysdeps/generic/bits/socket.h: Protect against multiple inclusion. + * sysdeps/mach/hurd/bits/ioctls.h: Likewise. + Fix typo to allow inclusion from sys/ioctl.h again. + +1998-04-16 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * iconvdata/*.[ch]: Clean up namespace. Optimize character lookup. + +1998-04-16 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * libc.map: Export __strerror_r. Remove _strerror_internal. + +1998-04-16 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/generic/strcasestr.c: Undefine strcasestr, not strstr. + Also undefine __strcasestr. + +1998-04-16 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * posix/regex.c: Rename __re_max_failures back to re_max_failures, + aliases do not work with global variables due to copy relocations. + +1998-04-20 15:12 Ulrich Drepper <drepper@cygnus.com> + + * manual/creature.texi: Fix type. Patch by Andreas Schwab. + +1998-04-20 13:47 Ulrich Drepper <drepper@cygnus.com> + + * signal/sighold.c: Include stddef.h for NULL definition. + * signal/sigrelse.c: Likewise. + * sysdeps/posix/sigignore.c: Likewise. + * sysdeps/posix/sigset.c: Likewise. + * sysdeps/posix/waitid.c: Likewise. + * sysdeps/unix/sysv/linux/rt_sigsuspend.c: Likewise. + * sysdeps/unix/sysv/linux/rt_sigtimedwait.c: Likewise. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise. + * wcsmbs/mbsrtowcs.c: Include stdlib.h for MB_CUR_MAX. + Patch by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>. + +1998-04-13 Mark Kettenis <kettenis@phys.uva.nl> + + * login/Makefile (headers): Remove utmpx.h and bits/utmpx.h. + * login/getutent.c (getutxent): Remove alias. + * login/getutent_r.c (setutxent, pututxline, endutxent): + Remove aliases. + * login/getutid.c (getutxid): Remove alias. + * login/getutline.c (getutxline): Remove alias. + * login/utmp.h: Add prototypes for __updwtmp, __getutent, + __getutid, __getutline and __pututline. + * login/utmpx.h: Moved to ... + * sysdeps/gnu/utmpx.h: ... here. [__USE_GNU]: Define UTMPX_FILE, + UTMPX_FILENAME, WTMPX_FILE and WTMPX_FILENAME, declare utmpxname + and updwtmpx. + * login/updwtmp.c: Moved to ... + * sysdeps/generic/updwtmp.c: ... here. (updwtmp): Generalized by + allowing file name transformation. + * sysdeps/gnu/updwtmp.c: New file. Use generic implementation with + additional file name transformation. + * sysdeps/unix/sysv/linux/updwtmp.c: Likewise. + * login/utmp_file.c: Moved to ... + * sysdeps/generic/utmp_file.c: ... here. (setutent_file): + Generalized by allowing file name transformation. Do not + print error message. Library functions should not print them. + Reported by Jim Meyering. + * sysdeps/gnu/utmp_file.c: New file. Use generic implementation + with additional file name transformation. + * sysdeps/unix/sysv/linux/utmp_file.c: Likewise. + * sysdeps/gnu/Makefile [$(subdir)=login] (sysdep_routines): Add + setutxent, getutxent, endutxent, getutxid, getutxid, getutxline, + pututxline, utmpxname and updwtmpx. (sysdep_headers): Add utmpx.h + and bits/utmpx.h. + * sysdeps/gnu/bits/utmpx.h [__USE_GNU] Include paths.h. + (_PATH_UTMPX): Define to _PATH_UTMP. (_PATH_WTMPX): Define to + _PATH_WTMPX. (RUN_LVL): Define only if __USE_GNU. (ACCOUNTING): + Define if __USE_GNU. + * sysdeps/gnu/setutxent.c: New file. + * sysdeps/gnu/getutxent.c: New file. + * sysdeps/gnu/endutxent.c: New file. + * sysdeps/gnu/getutxid.c: New file. + * sysdeps/gnu/getutxline.c: New file. + * sysdeps/gnu/pututxline.c: New file. + * sysdeps/gnu/utmpxname.c: New file. + * sysdeps/gnu/updwtmpx.c: New file. + * sysdeps/unix/sysv/linux/paths.h (_PATH_UTMP_DB): Remove. + * sysdeps/generic/bits/utmpx.h: Remove. + +1998-04-20 Ulrich Drepper <drepper@cygnus.com> + + * posix/wordexp-test.c (main): Initialize ifs element of ts for + ~root test. + +1998-04-17 07:53 H.J. Lu <hjl@gnu.org> + + * sysdeps/unix/sysv/linux/i386/s_pread64.S: Fix a typo. + +1998-04-17 11:32 Ulrich Drepper <drepper@cygnus.com> + + * libio/oldfileops.c (_IO_old_file_seekoff): Define temporary st + variable using _G_stat64. + * libio/fileops.c: Remove macro definition of fstat, it is in the + global header. + Reported by Thorsten Kukuk <kukuk@weber.uni-paderborn.de>. + +1998-04-17 Philip Blundell <pb@nexus.co.uk> + + * sysdeps/arm/strlen.S: New file, based on code by Matthew Wilcox + <willy@odie.barnet.ac.uk>. + +1998-04-16 Philip Blundell <Philip.Blundell@pobox.com> + + * inet/netinet/in.h (IN6_IS_ADDR_MC_NODELOCAL): New macro, + required by IPv6 Basic API. + (IN6_IS_ADDR_MC_LINKLOCAL): Likewise. + (IN6_IS_ADDR_MC_SITELOCAL): Likewise. + (IN6_IS_ADDR_MC_ORGLOCAL): Likewise. + (IN6_IS_ADDR_MC_GLOBAL): Likewise. + 1998-04-15 16:41 Ulrich Drepper <drepper@cygnus.com> Don't name internal representation since it might be different from @@ -24,7 +24,7 @@ please let me know. 1.3. When I try to compile glibc I get only error messages. What's wrong? 1.4. Do I need a special linker or archiver? -1.5. What tools do I need for powerpc? +1.5. Which compiler should I use for powerpc? 1.6. Do I need some more things to compile GNU C Library? 1.7. What version of the Linux kernel headers should be used? 1.8. When I run `nm -u libc.so' on the produced library I still @@ -203,25 +203,19 @@ may have native linker support, but it's moot right now, because glibc has not been ported to them. -1.5. What tools do I need for powerpc? +1.5. Which compiler should I use for powerpc? -{GK} For a successful installation you definitely need the most recent -tools. You can safely assume that anything earlier than binutils -2.8.1.0.17 and egcs-1.0 will have problems. We'd advise at the moment -binutils 2.8.1.0.18 and egcs-1.0.1. +{GK} You want to use egcs 1.0.1 or later (together with the right +versions of all the other tools, of course). -In fact, egcs 1.0.1 currently has two serious bugs that prevent a -clean make; one relates to switch statement folding, for which there -is a temporary patch at +In fact, egcs 1.0.1 has a serious bug that prevents a clean make, +relating to switch statement folding. It also causes the resulting +shared libraries to use more memory than they should. There is a +patch at: -<http://discus.anu.edu.au/~geoffk/egcs-1.0-geoffk.diff.gz> +<http://discus.anu.edu.au/~geoffk/egcs-1.0.1-geoffk.diff> -and the other relates to 'forbidden register spilled', for which the -workaround is to put - -CFLAGS-condvar.c += -fno-inline - -in configparms. Later versions of egcs may fix these problems. +Later versions of egcs may fix these problems. 1.6. Do I need some more things to compile GNU C Library? @@ -247,7 +241,8 @@ in configparms. Later versions of egcs may fix these problems. * When compiling for Linux, the header files of the Linux kernel must be available to the compiler as <linux/*.h> and <asm/*.h>. -* lots of disk space (~170MB for i?86-linux; more for RISC platforms). +* lots of disk space (~170MB for i?86-linux; more for RISC platforms, + as much as 400MB). * plenty of time. Compiling just the shared and static libraries for i?86-linux takes approximately 1h on an i586@133, or 2.5h on @@ -290,9 +285,6 @@ symbols: * symbols starting with _dl_* come from the dynamic linker -* symbols resolved by using libgcc.a - (__udivdi3, __umoddi3, or similar) - * weak symbols, which need not be resolved at all (fabs for example) Generally, you should make sure you find a real program which produces @@ -1141,7 +1133,7 @@ Answers were given by: {MK} Mark Kettenis, <kettenis@phys.uva.nl> {ZW} Zack Weinberg, <zack@rabi.phys.columbia.edu> {TK} Thorsten Kukuk, <kukuk@vt.uni-paderborn.de> -{GK} Geoffrey Keating, <Geoff.Keating@anu.edu.au> +{GK} Geoffrey Keating, <geoffk@ozemail.com.au> {HJ} H.J. Lu, <hjl@gnu.org> Local Variables: @@ -89,25 +89,19 @@ required. For Linux, get binutils-2.8.1.0.23 or later. Other systems may have native linker support, but it's moot right now, because glibc has not been ported to them. -??powerpc What tools do I need for powerpc? +??powerpc Which compiler should I use for powerpc? -{GK} For a successful installation you definitely need the most recent -tools. You can safely assume that anything earlier than binutils -2.8.1.0.17 and egcs-1.0 will have problems. We'd advise at the moment -binutils 2.8.1.0.18 and egcs-1.0.1. +{GK} You want to use egcs 1.0.1 or later (together with the right +versions of all the other tools, of course). -In fact, egcs 1.0.1 currently has two serious bugs that prevent a -clean make; one relates to switch statement folding, for which there -is a temporary patch at +In fact, egcs 1.0.1 has a serious bug that prevents a clean make, +relating to switch statement folding. It also causes the resulting +shared libraries to use more memory than they should. There is a +patch at: -<http://discus.anu.edu.au/~geoffk/egcs-1.0-geoffk.diff.gz> +<http://discus.anu.edu.au/~geoffk/egcs-1.0.1-geoffk.diff> -and the other relates to 'forbidden register spilled', for which the -workaround is to put - -CFLAGS-condvar.c += -fno-inline - -in configparms. Later versions of egcs may fix these problems. +Later versions of egcs may fix these problems. ?? Do I need some more things to compile GNU C Library? @@ -133,7 +127,8 @@ in configparms. Later versions of egcs may fix these problems. * When compiling for Linux, the header files of the Linux kernel must be available to the compiler as <linux/*.h> and <asm/*.h>. -* lots of disk space (~170MB for i?86-linux; more for RISC platforms). +* lots of disk space (~170MB for i?86-linux; more for RISC platforms, + as much as 400MB). * plenty of time. Compiling just the shared and static libraries for i?86-linux takes approximately 1h on an i586@133, or 2.5h on @@ -174,9 +169,6 @@ symbols: * symbols starting with _dl_* come from the dynamic linker -* symbols resolved by using libgcc.a - (__udivdi3, __umoddi3, or similar) - * weak symbols, which need not be resolved at all (fabs for example) Generally, you should make sure you find a real program which produces @@ -981,7 +973,7 @@ Answers were given by: {MK} Mark Kettenis, <kettenis@phys.uva.nl> {ZW} Zack Weinberg, <zack@rabi.phys.columbia.edu> {TK} Thorsten Kukuk, <kukuk@vt.uni-paderborn.de> -{GK} Geoffrey Keating, <Geoff.Keating@anu.edu.au> +{GK} Geoffrey Keating, <geoffk@ozemail.com.au> {HJ} H.J. Lu, <hjl@gnu.org> Local Variables: diff --git a/bits/socket.h b/bits/socket.h index 5dc1e65370..01844bc143 100644 --- a/bits/socket.h +++ b/bits/socket.h @@ -17,6 +17,9 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H 1 + #if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H # error "Never include <bits/socket.h> directly; use <sys/socket.h> instead." #endif @@ -196,3 +199,5 @@ struct linger int l_onoff; /* Nonzero to linger on close. */ int l_linger; /* Time to linger. */ }; + +#endif /* bits/socket.h */ diff --git a/csu/init.c b/csu/init.c index 2b7a2ef0ff..df08f6c918 100644 --- a/csu/init.c +++ b/csu/init.c @@ -1,5 +1,5 @@ /* Special startup support. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it @@ -26,7 +26,7 @@ write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#if defined __GNUC__ && __GNUC__ >= 2 +#if defined USE_IN_LIBIO && defined __GNUC__ && __GNUC__ >= 2 #undef _LIBC #include <libio.h> diff --git a/db2/compat.h b/db2/compat.h index 8652ad97ec..86909aeb13 100644 --- a/db2/compat.h +++ b/db2/compat.h @@ -1,6 +1,7 @@ /* Compatibility gunk for the db library. */ #include <sys/types.h> +#include <errno.h> #ifndef EFTYPE # define EFTYPE EINVAL diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index b0c8c465e4..70b5aeeeac 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -193,12 +193,15 @@ __assert_perror_fail (int errnum, const char *file, unsigned int line, const char *function) { + char errbuf[64]; char buf[64]; buf[sizeof buf - 1] = '\0'; _dl_sysdep_fatal ("BUG IN DYNAMIC LINKER ld.so: ", file, ": ", _itoa_word (line, buf + sizeof buf - 1, 10, 0), ": ", function ?: "", function ? ": " : "", - "Unexpected error: ", strerror (errnum), "\n", NULL); + "Unexpected error: ", + __strerror_r (errnum, errbuf, sizeof (errbuf)), "\n", + NULL); } diff --git a/iconv/Makefile b/iconv/Makefile index 783b1d55b5..e4cd0fc53d 100644 --- a/iconv/Makefile +++ b/iconv/Makefile @@ -21,10 +21,18 @@ # subdir := iconv +include ../Makeconfig + headers = iconv.h gconv.h routines = iconv_open iconv iconv_close \ gconv_open gconv gconv_close gconv_db gconv_conf \ - gconv_dl gconv_builtin gconv_simple + gconv_builtin gconv_simple +ifeq ($(elf),yes) +routines += gconv_dl +else +CFLAGS-gconv_db.c = -DSTATIC_GCONV +endif + distribute = gconv_builtin.h gconv_int.h others = iconv_prog diff --git a/iconv/gconv.c b/iconv/gconv.c index f8b7c8050d..aa58bdba7d 100644 --- a/iconv/gconv.c +++ b/iconv/gconv.c @@ -19,39 +19,58 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <assert.h> #include <gconv.h> +#include <sys/param.h> int internal_function -__gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, - size_t *outbytesleft, size_t *converted) +__gconv (gconv_t cd, const char **inbuf, const char *inbufend, char **outbuf, + char *outbufend, size_t *converted) { size_t last_step = cd->nsteps - 1; - size_t oldinbytes = *inbytesleft; int result; if (cd == (gconv_t) -1L) return GCONV_ILLEGAL_DESCRIPTOR; - cd->data[last_step].outbuf = outbuf ? *outbuf : NULL; - cd->data[last_step].outbufavail = 0; - cd->data[last_step].outbufsize = *outbytesleft; + assert (converted != NULL); + *converted = 0; - if (converted != NULL) - *converted = 0; + if (inbuf == NULL || *inbuf == NULL) + /* We just flush. */ + result = (*cd->steps->fct) (cd->steps, cd->data, NULL, NULL, converted, 1); + else + { + const char *last_start; - result = (*cd->steps->fct) (cd->steps, cd->data, - inbuf ? *inbuf : NULL, inbytesleft, - converted, inbuf == NULL || *inbuf == NULL); + assert (outbuf != NULL && *outbuf != NULL); + cd->data[last_step].outbuf = *outbuf; + cd->data[last_step].outbufend = outbufend; - if (inbuf != NULL && *inbuf != NULL) - *inbuf += oldinbytes - *inbytesleft; - if (outbuf != NULL && *outbuf != NULL) - { - *outbuf += cd->data[last_step].outbufavail; - *outbytesleft -= cd->data[last_step].outbufavail; + do + { + /* See whether the input size is reasoable for the output + size. If not adjust it. */ + size_t inlen = ((inbufend - *inbuf) / cd->steps->max_needed_from + * cd->steps->max_needed_from); + + if (cd->nsteps > 1) + inlen = MIN (inlen, (((outbufend - cd->data[last_step].outbuf) + / cd->steps[last_step].max_needed_to) + * cd->steps[last_step].max_needed_to)); + + last_start = *inbuf; + result = (*cd->steps->fct) (cd->steps, cd->data, inbuf, + *inbuf + inlen, converted, 0); + } + while (result == GCONV_EMPTY_INPUT && last_start != *inbuf + && *inbuf + cd->steps->min_needed_from <= inbufend); } + if (outbuf != NULL && *outbuf != NULL) + *outbuf = cd->data[last_step].outbuf; + return result; } diff --git a/iconv/gconv.h b/iconv/gconv.h index f3f80f4c14..cd0e3de1dc 100644 --- a/iconv/gconv.h +++ b/iconv/gconv.h @@ -57,8 +57,8 @@ struct gconv_loaded_object; /* Type of a conversion function. */ typedef int (*gconv_fct) __P ((struct gconv_step *, - struct gconv_step_data *, - __const char *, size_t *, size_t *, int)); + struct gconv_step_data *, __const char **, + __const char *, size_t *, int)); /* Constructor and destructor for local data for conversion step. */ typedef int (*gconv_init_fct) __P ((struct gconv_step *)); @@ -80,6 +80,13 @@ struct gconv_step gconv_init_fct init_fct; gconv_end_fct end_fct; + /* Information about the number of bytes needed or produced in this + step. This helps optimizing the buffer sizes. */ + int min_needed_from; + int max_needed_from; + int min_needed_to; + int max_needed_to; + void *data; /* Pointer to step-local data. */ }; @@ -88,8 +95,7 @@ struct gconv_step struct gconv_step_data { char *outbuf; /* Output buffer for this step. */ - size_t outbufavail; /* Bytes already available in output buffer. */ - size_t outbufsize; /* Size of output buffer. */ + char *outbufend; /* Address of first byte after the output buffer. */ int is_last; diff --git a/iconv/gconv_builtin.c b/iconv/gconv_builtin.c index 6b14804da3..a970fcc8f2 100644 --- a/iconv/gconv_builtin.c +++ b/iconv/gconv_builtin.c @@ -33,15 +33,25 @@ static struct builtin_map gconv_init_fct init; gconv_end_fct end; + int min_needed_from; + int max_needed_from; + int min_needed_to; + int max_needed_to; + } map[] = { #define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \ - Fct, Init, End) \ + Fct, Init, End, MinF, MaxF, MinT, MaxT) \ { \ name: Name, \ fct: Fct, \ init: Init, \ end: End, \ + \ + min_needed_from: MinF, \ + max_needed_from: MaxF, \ + min_needed_to: MinT, \ + max_needed_to: MaxT \ }, #define BUILTIN_ALIAS(From, To) @@ -66,4 +76,9 @@ __gconv_get_builtin_trans (const char *name, struct gconv_step *step) step->end_fct = map[cnt].end; step->counter = INT_MAX; step->shlib_handle = NULL; + + step->min_needed_from = map[cnt].min_needed_from; + step->max_needed_from = map[cnt].max_needed_from; + step->min_needed_to = map[cnt].min_needed_to; + step->max_needed_to = map[cnt].max_needed_to; } diff --git a/iconv/gconv_builtin.h b/iconv/gconv_builtin.h index 265dca1f01..3d214ff4f0 100644 --- a/iconv/gconv_builtin.h +++ b/iconv/gconv_builtin.h @@ -26,10 +26,12 @@ BUILTIN_ALIAS ("10646-1:1993/UCS4/", "ISO-10646/UCS4/") BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4", - __gconv_transform_internal_ucs4, NULL, NULL) + __gconv_transform_internal_ucs4, NULL, NULL, + 4, 4, 4, 4) BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, "INTERNAL", 1, "=ucs4->INTERNAL", - __gconv_transform_internal_ucs4, NULL, NULL) + __gconv_transform_internal_ucs4, NULL, NULL, + 4, 4, 4, 4) /* Please note that we need only one function for both direction. */ BUILTIN_ALIAS ("UTF8//", "ISO-10646/UTF8/") @@ -37,22 +39,27 @@ BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/") BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "ISO-10646/UTF8/", 1, "=INTERNAL->utf8", - __gconv_transform_internal_utf8, NULL, NULL) + __gconv_transform_internal_utf8, NULL, NULL, + 4, 4, 1, 6) BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13, "INTERNAL", 1, "=utf8->INTERNAL", - __gconv_transform_utf8_internal, NULL, NULL) + __gconv_transform_utf8_internal, NULL, NULL, + 1, 6, 4, 4) BUILTIN_ALIAS ("UCS2//", "ISO-10646/UCS2/") BUILTIN_ALIAS ("UCS-2//", "ISO-10646/UCS2/") BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "INTERNAL", 1, "=ucs2->INTERNAL", - __gconv_transform_ucs2_internal, NULL, NULL) + __gconv_transform_ucs2_internal, NULL, NULL, + 2, 2, 4, 4) BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2", - __gconv_transform_internal_ucs2, NULL, NULL) + __gconv_transform_internal_ucs2, NULL, NULL, + 4, 4, 2, 2) BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy", - __gconv_transform_dummy, NULL, NULL) + __gconv_transform_dummy, NULL, NULL, + 1, 1, 1, 1) diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c index c67a0d8f8c..ae5ba19e5d 100644 --- a/iconv/gconv_conf.c +++ b/iconv/gconv_conf.c @@ -47,7 +47,7 @@ static const char gconv_module_ext[] = MODULE_EXT; static struct gconv_module builtin_modules[] = { #define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \ - Fct, Init, End) \ + Fct, Init, End, MinF, MaxF, MinT, MaxT) \ { \ from_pattern: From, \ from_constpfx: ConstPfx, \ @@ -69,7 +69,7 @@ static const char * builtin_aliases[] = { #define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \ - Fct, Init, End) + Fct, Init, End, MinF, MaxF, MinT, MaxT) #define BUILTIN_ALIAS(From, To) From " " To, #include "gconv_builtin.h" diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c index 9f4366b7df..62d8f0540c 100644 --- a/iconv/gconv_db.c +++ b/iconv/gconv_db.c @@ -192,6 +192,7 @@ gen_steps (struct derivation_step *best, const char *toset, ? __strdup (current->result_set) : result[step_cnt + 1].from_name); +#ifndef STATIC_GCONV if (current->code->module_name[0] == '/') { /* Load the module, return handle for it. */ @@ -212,6 +213,7 @@ gen_steps (struct derivation_step *best, const char *toset, result[step_cnt].end_fct = shlib_handle->end_fct; } else +#endif /* It's a builtin transformation. */ __gconv_get_builtin_trans (current->code->module_name, &result[step_cnt]); @@ -230,7 +232,9 @@ gen_steps (struct derivation_step *best, const char *toset, { if (result[step_cnt].end_fct != NULL) (*result[step_cnt].end_fct) (&result[step_cnt]); +#ifndef STATIC_GCONV __gconv_release_shlib (result[step_cnt].shlib_handle); +#endif } free (result); *nsteps = 0; @@ -525,6 +529,7 @@ __gconv_find_transform (const char *toset, const char *fromset, result = find_derivation (toset, toset_expand, fromset, fromset_expand, handle, nsteps); +#ifndef STATIC_GCONV /* Increment the user counter. */ if (result == GCONV_OK) { @@ -548,6 +553,7 @@ __gconv_find_transform (const char *toset, const char *fromset, } while (cnt > 0); } +#endif /* Release the lock. */ __libc_lock_unlock (lock); @@ -568,6 +574,7 @@ __gconv_close_transform (struct gconv_step *steps, size_t nsteps) { int result = GCONV_OK; +#ifndef STATIC_GCONV /* Acquire the lock. */ __libc_lock_lock (lock); @@ -583,6 +590,7 @@ __gconv_close_transform (struct gconv_step *steps, size_t nsteps) /* Release the lock. */ __libc_lock_unlock (lock); +#endif return result; } diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h index a1475f8508..86e892f874 100644 --- a/iconv/gconv_int.h +++ b/iconv/gconv_int.h @@ -34,8 +34,8 @@ struct gconv_alias }; -/* Default size of intermediate buffers. */ -#define GCONV_DEFAULT_BUFSIZE 8160 +/* How many character should be conveted in one call? */ +#define GCONV_NCHAR_GOAL 8160 /* Structure describing one loaded shared object. This normally are @@ -99,9 +99,8 @@ extern int __gconv_close (gconv_t cd) according to rules described by CD and place up to *OUTBYTESLEFT bytes in buffer starting at *OUTBUF. Return number of written characters in *CONVERTED if this pointer is not null. */ -extern int __gconv (gconv_t __cd, const char **__inbuf, size_t *__inbytesleft, - char **__outbuf, size_t *__outbytesleft, - size_t *__converted) +extern int __gconv (gconv_t __cd, const char **__inbuf, const char *inbufend, + char **__outbuf, char *outbufend, size_t *__converted) internal_function; /* Return in *HANDLE a pointer to an array with *NSTEPS elements describing @@ -149,8 +148,8 @@ extern void __gconv_get_builtin_trans (const char *__name, #ifdef _LIBC # define __BUILTIN_TRANS(Name) \ extern int Name (struct gconv_step *__step, struct gconv_step_data *__data, \ - const char *__inbuf, size_t *__inlen, size_t *__written, \ - int __do_flush) + const char **__inbuf, const char *__inbufend, \ + size_t *__written, int __do_flush) __BUILTIN_TRANS (__gconv_transform_dummy); __BUILTIN_TRANS (__gconv_transform_ascii_internal); diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c index d82dcfee48..831794fc22 100644 --- a/iconv/gconv_open.c +++ b/iconv/gconv_open.c @@ -62,21 +62,24 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle) for (cnt = 0; cnt < nsteps; ++cnt) { /* If this is the last step we must not allocate an output - buffer. Signal this to the initializer. */ + buffer. */ data[cnt].is_last = cnt == nsteps - 1; /* We use the `mbstate_t' member in DATA. */ data[cnt].statep = &data[cnt].__state; /* Allocate the buffer. */ - data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE; - data[cnt].outbuf = (char *) malloc (data[cnt].outbufsize); - if (data[cnt].outbuf == NULL) + if (!data[cnt].is_last) { - res = GCONV_NOMEM; - break; + data[cnt].outbuf = + (char *) malloc (GCONV_NCHAR_GOAL + * steps[cnt].max_needed_to); + if (data[cnt].outbuf == NULL) + { + res = GCONV_NOMEM; + break; + } } - data[cnt].outbufavail = 0; } } } diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index b72e61edcc..f2fec12fb8 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -35,7 +35,7 @@ /* These are definitions used by some of the functions for handling UTF-8 encoding below. */ -static const wchar_t encoding_mask[] = +static const uint32_t encoding_mask[] = { ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff }; @@ -49,8 +49,8 @@ static const unsigned char encoding_byte[] = int __gconv_transform_dummy (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inlen, size_t *written, - int do_flush) + const char **inbuf, const char *inbufend, + size_t *written, int do_flush) { size_t do_write; @@ -60,12 +60,12 @@ __gconv_transform_dummy (struct gconv_step *step, struct gconv_step_data *data, do_write = 0; else { - do_write = MIN (*inlen, data->outbufsize - data->outbufavail); + do_write = MIN (inbufend - *inbuf, data->outbufend - data->outbuf); memcpy (data->outbuf, inbuf, do_write); - *inlen -= do_write; - data->outbufavail += do_write; + *inbuf -= do_write; + *data->outbuf += do_write; } /* ### TODO Actually, this number must be devided according to the @@ -83,934 +83,330 @@ __gconv_transform_dummy (struct gconv_step *step, struct gconv_step_data *data, format is, if any, the endianess. The Unicode/ISO 10646 says that unless some higher protocol specifies it differently, the byte order is big endian.*/ -int -__gconv_transform_internal_ucs4 (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 4 +#define MIN_NEEDED_TO 4 +#define FROM_DIRECTION 1 +#define FROM_LOOP internal_ucs4_loop +#define TO_LOOP internal_ucs4_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_internal_ucs4 + + +static inline int +internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend, + unsigned char **outptrp, unsigned char *outend, + mbstate_t *state, void *data, size_t *converted) { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write = 0; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; + size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; int result; - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - int save_errno = errno; - - result = GCONV_OK; - do - { - size_t n_convert = (MIN (*inlen, - (data->outbufsize - data->outbufavail)) - / sizeof (wchar_t)); - #if __BYTE_ORDER == __LITTLE_ENDIAN - /* Sigh, we have to do some real work. */ - wchar_t *outbuf = (wchar_t *) &data->outbuf[data->outbufavail]; - size_t cnt; + /* Sigh, we have to do some real work. */ + size_t cnt; - for (cnt = 0; cnt < n_convert; ++cnt) - outbuf[cnt] = bswap_32 (((wchar_t *) inbuf)[cnt]); + for (cnt = 0; cnt < n_convert; ++cnt) + *((uint32_t *) outptr)++ = bswap_32 (*((uint32_t *) inptr)++); + *inptrp = inptr; + *outptrp = outptr; #elif __BYTE_ORDER == __BIG_ENDIAN - /* Simply copy the data. */ - memcpy (&data->outbuf[data->outbufsize], inbuf, - n_convert * sizeof (wchar_t)); + /* Simply copy the data. */ + *inptrp = inptr + n_convert * 4; + *outptrp = __mempcpy (outptr, inptr, n_convert * 4); #else # error "This endianess is not supported." #endif - *inlen -= n_convert * sizeof (wchar_t); - inbuf += n_convert * sizeof (wchar_t); - data->outbufavail += n_convert * sizeof (wchar_t); - do_write += n_convert; - - if (*inlen > 0 && *inlen < sizeof (wchar_t)) - { - /* We have an incomplete character at the end. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - if (data->is_last) - { - /* This is the last step. */ - result = (*inlen < sizeof (wchar_t) - ? GCONV_EMPTY_INPUT : GCONV_FULL_OUTPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen >= sizeof (wchar_t) && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} - - -/* Convert from ISO 646-IRV to the internal (UCS4-like) format. */ -int -__gconv_transform_ascii_internal (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write = 0; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - const unsigned char *newinbuf = inbuf; - int save_errno = errno; - - result = GCONV_OK; - do - { - size_t actually = 0; - size_t cnt = 0; - - while (data->outbufavail + sizeof (wchar_t) <= data->outbufsize - && cnt < *inlen) - { - if (*newinbuf > '\x7f') - { - /* This is no correct ANSI_X3.4-1968 character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - /* It's an one byte sequence. */ - *(wchar_t *) &data->outbuf[data->outbufavail] - = (wchar_t) *newinbuf; - data->outbufavail += sizeof (wchar_t); - ++actually; - - ++newinbuf; - ++cnt; - } - - /* Remember how much we converted. */ - do_write += cnt * sizeof (wchar_t); - *inlen -= cnt; - - /* Check whether an illegal character appeared. */ - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inlen == 0 ? GCONV_EMPTY_INPUT : GCONV_FULL_OUTPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen > 0 && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } - - if (written != NULL && data->is_last) - *written = do_write / sizeof (wchar_t); - - return result; -} - - -/* Convert from ISO 10646/UCS to ISO 646-IRV. */ -int -__gconv_transform_internal_ascii (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - const wchar_t *newinbuf = (const wchar_t *) inbuf; - int save_errno = errno; - do_write = 0; - - result = GCONV_OK; - do - { - size_t actually = 0; - size_t cnt = 0; - - while (data->outbufavail < data->outbufsize - && cnt + 3 < *inlen) - { - if (*newinbuf < L'\0' || *newinbuf > L'\x7f') - { - /* This is no correct ANSI_X3.4-1968 character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - /* It's an one byte sequence. */ - data->outbuf[data->outbufavail++] = (char) *newinbuf; - ++actually; - - ++newinbuf; - cnt += sizeof (wchar_t); - } - - /* Remember how much we converted. */ - do_write += cnt / sizeof (wchar_t); - *inlen -= cnt; - - /* Check whether an illegal character appeared. */ - if (result != GCONV_OK) - break; - - /* Check for incomplete input. */ - if (*inlen > 0 && *inlen < sizeof (wchar_t)) - { - /* We have an incomplete character at the end. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - if (data->is_last) - { - /* This is the last step. */ - result = *inlen == 0 ? GCONV_EMPTY_INPUT : GCONV_FULL_OUTPUT; - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen > 0 && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} - - -int -__gconv_transform_internal_utf8 (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - const wchar_t *newinbuf = (const wchar_t *) inbuf; - int save_errno = errno; - do_write = 0; - - result = GCONV_OK; - do - { - size_t cnt = 0; - - while (data->outbufavail < data->outbufsize - && cnt * sizeof (wchar_t) + 3 < *inlen) - { - wchar_t wc = newinbuf[cnt]; - - if (wc < 0 && wc > 0x7fffffff) - { - /* This is no correct ISO 10646 character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (wc < 0x80) - /* It's an one byte sequence. */ - data->outbuf[data->outbufavail++] = (char) wc; - else - { - size_t step; - size_t start; - - for (step = 2; step < 6; ++step) - if ((wc & encoding_mask[step - 2]) == 0) - break; - - if (data->outbufavail + step >= data->outbufsize) - /* Too long. */ - break; - - start = data->outbufavail; - data->outbufavail += step; - data->outbuf[start] = encoding_byte[step - 2]; - --step; - do - { - data->outbuf[start + step] = 0x80 | (wc & 0x3f); - wc >>= 6; - } - while (--step > 0); - data->outbuf[start] |= wc; - } - - ++cnt; - } - - /* Remember how much we converted. */ - do_write += cnt; - *inlen -= cnt * sizeof (wchar_t); - newinbuf += cnt; - - /* Check whether an illegal character appeared. */ - if (result != GCONV_OK) - break; - - /* Check for incomplete input. */ - if (*inlen > 0 && *inlen < sizeof (wchar_t)) - { - /* We have an incomplete character at the end. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - if (data->is_last) - { - /* This is the last step. */ - result = *inlen == 0 ? GCONV_EMPTY_INPUT : GCONV_FULL_OUTPUT; - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen > 0 && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} - - -int -__gconv_transform_utf8_internal (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - } - } + /* Determine the status. */ + if (*outptrp == outend) + result = GCONV_FULL_OUTPUT; + else if (*inptrp == inend) + result = GCONV_EMPTY_INPUT; else - { - int save_errno = errno; - int extra = 0; - do_write = 0; - - result = GCONV_OK; - do - { - wchar_t *outbuf = (wchar_t *) &data->outbuf[data->outbufavail]; - size_t cnt = 0; - size_t actually = 0; - - while (data->outbufavail + sizeof (wchar_t) <= data->outbufsize - && cnt < *inlen) - { - size_t start = cnt; - wchar_t value; - unsigned char byte; - int count; - - /* Next input byte. */ - byte = inbuf[cnt++]; - - if (byte < 0x80) - { - /* One byte sequence. */ - count = 0; - value = byte; - } - else if ((byte & 0xe0) == 0xc0) - { - count = 1; - value = byte & 0x1f; - } - else if ((byte & 0xf0) == 0xe0) - { - /* We expect three bytes. */ - count = 2; - value = byte & 0x0f; - } - else if ((byte & 0xf8) == 0xf0) - { - /* We expect four bytes. */ - count = 3; - value = byte & 0x07; - } - else if ((byte & 0xfc) == 0xf8) - { - /* We expect five bytes. */ - count = 4; - value = byte & 0x03; - } - else if ((byte & 0xfe) == 0xfc) - { - /* We expect six bytes. */ - count = 5; - value = byte & 0x01; - } - else - { - /* This is an illegal encoding. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (cnt + count > *inlen) - { - /* We don't have enough input. */ - --cnt; - extra = count; - break; - } - - /* Read the possible remaining bytes. */ - while (count > 0) - { - byte = inbuf[cnt++]; - --count; - - if ((byte & 0xc0) != 0x80) - { - /* This is an illegal encoding. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - value <<= 6; - value |= byte & 0x3f; - } - - if (result != GCONV_OK) - { - cnt = start; - break; - } - - *outbuf++ = value; - ++actually; - } - - /* Remember how much we converted. */ - do_write += actually; - *inlen -= cnt; - inbuf += cnt; - - data->outbufavail += actually * sizeof (wchar_t); - - /* Check whether an illegal character appeared. */ - if (result != GCONV_OK) - { - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (*inlen > 0 && *inlen < extra) - { - /* We have an incomplete character at the end. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - if (data->is_last) - { - /* This is the last step. */ - result = (data->outbufavail + sizeof (wchar_t) > data->outbufsize - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen > 0 && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } + result = GCONV_INCOMPLETE_INPUT; - if (written != NULL && data->is_last) - *written = do_write; + if (converted != NULL) + converted += n_convert; return result; } +#include <iconv/skeleton.c> -int -__gconv_transform_ucs2_internal (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - } - } - else - { - const uint16_t *newinbuf = (const uint16_t *) inbuf; - int save_errno = errno; - do_write = 0; - - do - { - wchar_t *outbuf = (wchar_t *) &data->outbuf[data->outbufavail]; - size_t actually = 0; - - errno = 0; - while (data->outbufavail + 4 <= data->outbufsize - && *inlen >= 2) - { +/* Convert from ISO 646-IRV to the internal (UCS4-like) format. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 1 +#define MIN_NEEDED_TO 4 +#define FROM_DIRECTION 1 +#define FROM_LOOP ascii_internal_loop +#define TO_LOOP ascii_internal_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_ascii_internal + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + if (*inptr > '\x7f') \ + { \ + /* This is no correct ANSI_X3.4-1968 character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* It's an one byte sequence. */ \ + *((uint32_t *) outptr)++ = *inptr++; \ + } +#include <iconv/loop.c> +#include <iconv/skeleton.c> + + +/* Convert from the internal (UCS4-like) format to ISO 646-IRV. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 4 +#define MIN_NEEDED_TO 1 +#define FROM_DIRECTION 1 +#define FROM_LOOP internal_ascii_loop +#define TO_LOOP internal_ascii_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_internal_ascii + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + if (*((uint32_t *) inptr) > '\x7f') \ + { \ + /* This is no correct ANSI_X3.4-1968 character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* It's an one byte sequence. */ \ + *outptr++ = *((uint32_t *) inptr)++; \ + } +#include <iconv/loop.c> +#include <iconv/skeleton.c> + + +/* Convert from the internal (UCS4-like) format to UTF-8. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 4 +#define MIN_NEEDED_TO 1 +#define MAX_NEEDED_TO 6 +#define FROM_DIRECTION 1 +#define FROM_LOOP internal_utf8_loop +#define TO_LOOP internal_utf8_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_internal_utf8 + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t wc = *((uint32_t *) inptr); \ + \ + /* Since we control every character we read this cannot happen. */ \ + assert (wc <= 0x7fffffff); \ + \ + if (wc < 0x80) \ + /* It's an one byte sequence. */ \ + *outptr++ = (unsigned char) wc; \ + else \ + { \ + size_t step; \ + char *start; \ + \ + for (step = 2; step < 6; ++step) \ + if ((wc & encoding_mask[step - 2]) == 0) \ + break; \ + \ + if (outptr + step >= outend) \ + { \ + /* Too long. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + start = outptr; \ + *outptr = encoding_byte[step - 2]; \ + outptr += step; \ + --step; \ + do \ + { \ + start[step] = 0x80 | (wc & 0x3f); \ + wc >>= 6; \ + } \ + while (--step > 0); \ + start[0] |= wc; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> +#include <iconv/skeleton.c> + + +/* Convert from UTF-8 to the internal (UCS4-like) format. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 6 +#define MIN_NEEDED_TO 4 +#define FROM_DIRECTION 1 +#define FROM_LOOP utf8_internal_loop +#define TO_LOOP utf8_internal_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_utf8_internal + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch; \ + uint_fast32_t cnt; \ + uint_fast32_t i; \ + \ + /* Next input byte. */ \ + ch = *inptr; \ + \ + if (ch < 0x80) \ + /* One byte sequence. */ \ + cnt = 1; \ + else if ((ch & 0xe0) == 0xc0) \ + { \ + cnt = 2; \ + ch &= 0x1f; \ + } \ + else if ((ch & 0xf0) == 0xe0) \ + { \ + /* We expect three bytes. */ \ + cnt = 3; \ + ch &= 0x0f; \ + } \ + else if ((ch & 0xf8) == 0xf0) \ + { \ + /* We expect four bytes. */ \ + cnt = 4; \ + ch &= 0x07; \ + } \ + else if ((ch & 0xfc) == 0xf8) \ + { \ + /* We expect five bytes. */ \ + cnt = 5; \ + ch &= 0x03; \ + } \ + else if ((ch & 0xfe) == 0xfc) \ + { \ + /* We expect six bytes. */ \ + cnt = 6; \ + ch &= 0x01; \ + } \ + else \ + { \ + /* This is an illegal encoding. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + if (NEED_LENGTH_TEST && inptr + cnt >= inend) \ + { \ + /* We don't have enough input. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + /* Read the possible remaining bytes. */ \ + for (i = 1; i < cnt; ++i) \ + { \ + uint32_t byte = inptr[i]; \ + \ + if ((byte & 0xc0) != 0x80) \ + { \ + /* This is an illegal encoding. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + ch <<= 6; \ + ch |= byte & 0x3f; \ + } \ + \ + /* Now adjust the pointers and store the result. */ \ + inptr += cnt; \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> +#include <iconv/skeleton.c> + + +/* Convert from UCS2 to the internal (UCS4-like) format. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 +#define FROM_DIRECTION 1 +#define FROM_LOOP ucs2_internal_loop +#define TO_LOOP ucs2_internal_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_ucs2_internal + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP #if __BYTE_ORDER == __LITTLE_ENDIAN - outbuf[actually++] = (wchar_t) bswap_16 (*newinbuf++); +# define BODY \ + *((uint32_t *) outptr)++ = bswap_16 (*((uint16_t *) inptr)++); #else - outbuf[actually++] = (wchar_t) *newinbuf++; +# define BODY \ + *((uint32_t *) outptr)++ = *((uint16_t *) inptr)++; #endif - data->outbufavail += 4; - *inlen -= 2; - } - - /* Remember how much we converted. */ - do_write += actually * sizeof (wchar_t); - - if (*inlen == 1) - { - /* We have an incomplete character at the end. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - /* Check whether an illegal character appeared. */ - if (errno != 0) - { - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (data->is_last) - { - /* This is the last step. */ - result = (data->outbufavail + sizeof (wchar_t) > data->outbufsize - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen > 0 && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} - - -int -__gconv_transform_internal_ucs2 (struct gconv_step *step, - struct gconv_step_data *data, - const char *inbuf, size_t *inlen, - size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - /* Clear the state. */ - memset (data->statep, '\0', sizeof (mbstate_t)); - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - const wchar_t *newinbuf = (const wchar_t *) inbuf; - int save_errno = errno; - do_write = 0; - - do - { - uint16_t *outbuf = (uint16_t *) &data->outbuf[data->outbufavail]; - size_t actually = 0; - - errno = 0; - - while (data->outbufavail + 2 <= data->outbufsize - && *inlen >= 4) - { - if (*newinbuf >= 0x10000) - { - __set_errno (EILSEQ); - break; - } +#include <iconv/loop.c> +#include <iconv/skeleton.c> + + +/* Convert from the internal (UCS4-like) format to UCS2. */ +#define DEFINE_INIT 0 +#define DEFINE_FINI 0 +#define MIN_NEEDED_FROM 4 +#define MIN_NEEDED_TO 2 +#define FROM_DIRECTION 1 +#define FROM_LOOP internal_ucs2_loop +#define TO_LOOP internal_ucs2_loop /* This is not used. */ +#define FUNCTION_NAME __gconv_transform_internal_ucs2 + +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP #if __BYTE_ORDER == __LITTLE_ENDIAN - /* Please note that we use the `uint32_t' pointer as a - `uint16_t' pointer which works since we are on a - little endian machine. */ - outbuf[actually++] = bswap_16 (*((uint16_t *) newinbuf)); - ++newinbuf; +# define BODY \ + { \ + if (*((uint32_t *) inptr) >= 0x10000) \ + { \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + /* Please note that we use the `uint32_t' from-pointer as an `uint16_t' \ + pointer which works since we are on a little endian machine. */ \ + *((uint16_t *) outptr)++ = bswap_16 (*((uint16_t *) inptr)); \ + inptr += 4; \ + } #else - outbuf[actually++] = *newinbuf++; +# define BODY \ + { \ + if (*((uint32_t *) inptr) >= 0x10000) \ + { \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + *((uint16_t *) outptr)++ = *((uint32_t *) inptr)++; \ + } #endif - *inlen -= 4; - data->outbufavail += 2; - } - - /* Remember how much we converted. */ - do_write += (const char *) newinbuf - inbuf; - - if (*inlen > 0 && *inlen < 4) - { - /* We have an incomplete input character. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - /* Check whether an illegal character appeared. */ - if (errno != 0) - { - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (data->is_last) - { - /* This is the last step. */ - result = *inlen == 0 ? GCONV_EMPTY_INPUT : GCONV_FULL_OUTPUT; - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inlen > 0 && result == GCONV_EMPTY_INPUT); - - __set_errno (save_errno); - } - - if (written != NULL && data->is_last) - *written = do_write / sizeof (wchar_t); - - return result; -} +#include <iconv/loop.c> +#include <iconv/skeleton.c> diff --git a/iconv/iconv.c b/iconv/iconv.c index fc0ed41b50..2f57295097 100644 --- a/iconv/iconv.c +++ b/iconv/iconv.c @@ -32,10 +32,27 @@ iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { gconv_t gcd = (gconv_t) cd; + char *outstart = outbuf ? *outbuf : NULL; size_t converted; int result; - result = __gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted); + if (inbuf == NULL || *inbuf == NULL) + { + result = __gconv (gcd, NULL, NULL, outbuf, outstart + *outbytesleft, + &converted); + } + else + { + const char *instart = *inbuf; + + result = __gconv (gcd, inbuf, *inbuf + *inbytesleft, outbuf, + *outbuf + *outbytesleft, &converted); + + *inbytesleft -= *inbuf - instart; + } + if (outstart != NULL) + *outbytesleft -= *outbuf - outstart; + switch (result) { case GCONV_ILLEGAL_DESCRIPTOR: diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c index 569bd3b3ec..2452a88c5e 100644 --- a/iconv/iconv_prog.c +++ b/iconv/iconv_prog.c @@ -299,12 +299,15 @@ process_block (iconv_t cd, const char *addr, size_t len, FILE *output) { #define OUTBUF_SIZE 32768 char outbuf[OUTBUF_SIZE]; - char *outptr = outbuf; - size_t outlen = OUTBUF_SIZE; + char *outptr; + size_t outlen; + size_t n; while (len > 0) { - size_t n = iconv (cd, &addr, &len, &outptr, &outlen); + outptr = outbuf; + outlen = OUTBUF_SIZE; + n = iconv (cd, &addr, &len, &outptr, &outlen); if (outptr != outbuf) { diff --git a/iconv/loop.c b/iconv/loop.c new file mode 100644 index 0000000000..b8657d574c --- /dev/null +++ b/iconv/loop.c @@ -0,0 +1,226 @@ +/* Conversion loop frame work. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file provides a frame for the reader loop in all conversion modules. + The actual code must (of course) be provided in the actual module source + code but certain actions can be written down generically, with some + customization options which are these: + + MIN_NEEDED_INPUT minimal number of input bytes needed for the next + conversion. + MIN_NEEDED_OUTPUT minimal number of bytes produced by the next round + of conversion. + + MAX_NEEDED_INPUT you guess it, this is the maximal number of input + bytes needed. It defaults to MIN_NEEDED_INPUT + MAX_NEEDED_OUTPUT likewise for output bytes. + + Both values have a default of 1. + + LOOPFCT name of the function created. If not specified + the name is `loop' but this prevents the use + of multiple functions in the same file. + + COUNT_CONVERTED optional macro which is used to count the actual + number of characters converted. For some conversion + it is easy to compute the value afterwards, but for + others explicit counting is cheaper. + + BODY this is supposed to expand to the body of the loop. + The user must provide this. +*/ + +#include <gconv.h> +#include <sys/param.h> /* For MIN. */ +#define __need_size_t +#include <stddef.h> + + +/* We need at least one byte for the next round. */ +#ifndef MIN_NEEDED_INPUT +# define MIN_NEEDED_INPUT 1 +#endif + +/* Let's see how many bytes we produce. */ +#ifndef MAX_NEEDED_INPUT +# define MAX_NEEDED_INPUT MIN_NEEDED_INPUT +#endif + +/* We produce at least one byte in the next round. */ +#ifndef MIN_NEEDED_OUTPUT +# define MIN_NEEDED_OUTPUT 1 +#endif + +/* Let's see how many bytes we produce. */ +#ifndef MAX_NEEDED_OUTPUT +# define MAX_NEEDED_OUTPUT MIN_NEEDED_OUTPUT +#endif + +/* Default name for the function. */ +#ifndef LOOPFCT +# define LOOPFCT loop +#endif + +/* Make sure we have a loop body. */ +#ifndef BODY +# error "Definition of BODY missing for function" LOOPFCT +#endif + +/* We can calculate the number of converted characters easily if one + of the character sets has a fixed width. */ +#ifndef COUNT_CONVERTED +# if MIN_NEEDED_INPUT == MAX_NEEDED_INPUT +# if MIN_NEEDED_OUTPUT == MAX_NEEDED_OUTPUT +/* Decide whether one of the charsets has size 1. */ +# if MIN_NEEDED_INPUT == 1 +# define COUNT_CONVERTED (inptr - *inptrp) +# elif MIN_NEEDED_OUTPUT == 1 +# define COUNT_CONVERTED (outptr - *outptrp) +# else +/* Else we should see whether one of the two numbers is a power of 2. */ +# define COUNT_CONVERTED \ + ((MIN_NEEDED_INPUT & (-MIN_NEEDED_INPUT)) == MIN_NEEDED_INPUT \ + ? (inptr - *inptrp) : (outptr - *outptrp)) +# endif +# else +# define COUNT_CONVERTED (inptr - *inptrp) +# endif +# elif MIN_NEEDED_OUTPUT == MAX_NEEDED_OUTPUT +# define COUNT_CONVERTED (outptr - *outptrp) +# endif +#endif + + +/* The function returns the status, as defined in gconv.h. */ +static inline int +LOOPFCT (const unsigned char **inptrp, const unsigned char *inend, + unsigned char **outptrp, unsigned char *outend, mbstate_t *state, + void *data, size_t *converted) +{ + int result = GCONV_OK; + const unsigned char *inptr = *inptrp; + unsigned char *outptr = *outptrp; +#ifndef COUNT_CONVERTED + size_t done = 0; +#endif + + /* We run one loop where we avoid checks for underflow/overflow of the + buffers to speed up the conversion a bit. */ + size_t min_in_rounds = (inend - inptr) / MAX_NEEDED_INPUT; + size_t min_out_rounds = (outend - outptr) / MAX_NEEDED_OUTPUT; + size_t min_rounds = MIN (min_in_rounds, min_out_rounds); + +#undef NEED_LENGTH_TEST +#define NEED_LENGTH_TEST 0 + while (min_rounds-- > 0) + { + /* Here comes the body the user provides. It can stop with RESULT + set to GCONV_INCOMPLETE_INPUT (if the size of the input characters + vary in size), GCONV_ILLEGAL_INPUT, or GCONV_FULL_OUTPUT (if the + output characters vary in size. */ + BODY + + /* If necessary count the successful conversion. */ +#ifndef COUNT_CONVERTED + ++done; +#endif + } + + if (result == GCONV_OK) + { +#if MIN_NEEDED_INPUT == MAX_NEEDED_INPUT \ + && MIN_NEEDED_OUTPUT == MAX_NEEDED_OUTPUT + /* We don't need to start another loop since we were able to determine + the maximal number of characters to copy in advance. What remains + to be determined is the status. */ + if (inptr == inend) + /* No more input. */ + result = GCONV_EMPTY_INPUT; + else if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend) + || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend)) + /* Overflow in the output buffer. */ + result = GCONV_FULL_OUTPUT; + else + /* We have something left in the input buffer. */ + result = GCONV_INCOMPLETE_INPUT; +#else + result = GCONV_EMPTY_INPUT; + +# undef NEED_LENGTH_TEST +# define NEED_LENGTH_TEST 1 + while (inptr != inend) + { + /* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the + compiler generating better code. It will optimized away + since MIN_NEEDED_OUTPUT is always a constant. */ + if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend) + || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend)) + { + /* Overflow in the output buffer. */ + result = GCONV_FULL_OUTPUT; + break; + } + if (MIN_NEEDED_INPUT > 1 && inptr + MIN_NEEDED_INPUT > inend) + { + /* We don't have enough input for another complete input + character. */ + result = GCONV_INCOMPLETE_INPUT; + break; + } + + /* Here comes the body the user provides. It can stop with + RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the + input characters vary in size), GCONV_ILLEGAL_INPUT, or + GCONV_FULL_OUTPUT (if the output characters vary in size. */ + BODY + + /* If necessary count the successful conversion. */ +# ifndef COUNT_CONVERTED + ++done; +# endif + } +#endif /* Input and output charset are not both fixed width. */ + } + + /* Add the number of characters we actually converted. */ +#ifdef COUNT_CONVERTED + *converted += COUNT_CONVERTED; +#else + *converted += done; +#endif + + /* Update the pointers pointed to by the parameters. */ + *inptrp = inptr; + *outptrp = outptr; + + return result; +} + + +/* We remove the macro definitions so that we can include this file again + for the definition of another function. */ +#undef MIN_NEEDED_INPUT +#undef MAX_NEEDED_INPUT +#undef MIN_NEEDED_OUTPUT +#undef MAX_NEEDED_OUTPUT +#undef LOOPFCT +#undef COUNT_CONVERTED +#undef BODY +#undef LOOPFCT diff --git a/iconv/skeleton.c b/iconv/skeleton.c new file mode 100644 index 0000000000..3582f14110 --- /dev/null +++ b/iconv/skeleton.c @@ -0,0 +1,328 @@ +/* Skeleton for a converison module. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file can be included to provide definitions of several things + many modules have in common. It can be customized using the following + macros: + + DEFINE_INIT define the default initializer. This requires the + following symbol to be defined. + + CHARSET_NAME string with official name of the coded character + set (in all-caps) + + DEFINE_FINI define the default destructor function. + + MIN_NEEDED_FROM minimal number of bytes needed for the from-charset. + MIN_NEEDED_TO likewise for the to-charset. + + MAX_NEEDED_FROM maximal number of bytes needed for the from-charset. + This macro is optional, it defaults to MIN_NEEDED_FROM. + MAX_NEEDED_TO likewise for the to-charset. + + DEFINE_DIRECTION_OBJECTS + two objects will be defined to be used when the + `gconv' function must only distinguish two + directions. This is implied by DEFINE_INIT. + If this macro is not defined the following + macro must be available. + + FROM_DIRECTION this macro is supposed to return a value != 0 + if we convert from the current character set, + otherwise it return 0. + + EMIT_SHIFT_TO_INIT this symbol is optional. If it is defined it + defines some code which writes out a sequence + of characters which bring the current state into + the initial state. + + FROM_LOOP name of the function implementing the conversion + from the current characters. + TO_LOOP likewise for the other direction + + RESET_STATE in case of an error we must reset the state for + the rerun so this macro must be defined for + stateful encodings. It takes an argument which + is nonzero when saving. + + RESET_INPUT_BUFFER If the input character sets allow this the macro + can be defined to reset the input buffer pointers + to cover only those characters up to the error. + + FUNCTION_NAME if not set the conversion function is named `gconv'. + */ + +#include <assert.h> +#include <gconv.h> +#include <string.h> +#define __need_size_t +#define __need_NULL +#include <stddef.h> + + +/* The direction objects. */ +#if DEFINE_DIRECTION_OBJECTS || DEFINE_INIT +static int from_object; +static int to_object; + +# ifndef FROM_DIRECTION +# define FROM_DIRECTION step->data == &from_object +# endif +#else +# ifndef FROM_DIRECTION +# error "FROM_DIRECTION must be provided if direction objects are not used" +# endif +#endif + + +/* How many bytes are needed at most for the from-charset. */ +#ifndef MAX_NEEDED_FROM +# define MAX_NEEDED_FROM MIN_NEEDED_FROM +#endif + +/* Same for the to-charset. */ +#ifndef MAX_NEEDED_TO +# define MAX_NEEDED_TO MIN_NEEDED_TO +#endif + + +/* For conversions from a fixed width character sets to another fixed width + character set we we can define RESET_INPUT_BUFFER is necessary. */ +#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE +# if MIN_NEEDED_FROM == MAX_NEEDED_FROM && MIN_NEEDED_TO == MAX_NEEDED_TO +/* We have to used these `if's here since the compiler cannot know that + (outbuf - outerr) is always divisible by MIN_NEEDED_TO. */ +# define RESET_INPUT_BUFFER \ + if (MIN_NEEDED_FROM % MIN_NEEDED_TO == 0) \ + *inbuf -= (outbuf - outerr) * (MIN_NEEDED_FROM / MIN_NEEDED_TO); \ + else if (MIN_NEEDED_TO % MIN_NEEDED_FROM == 0) \ + *inbuf -= (outbuf - outerr) / (MIN_NEEDED_TO / MIN_NEEDED_FROM); \ + else \ + *inbuf -= ((outbuf - outerr) / MIN_NEEDED_TO) * MIN_NEEDED_FROM +# endif +#endif + + +/* The default init function. It simply matches the name and initializes + the step data to point to one of the objects above. */ +#if DEFINE_INIT +# ifndef CHARSET_NAME +# error "CHARSET_NAME not defined" +# endif + +int +gconv_init (struct gconv_step *step) +{ + /* Determine which direction. */ + if (__strcasestr (step->from_name, CHARSET_NAME) != NULL) + step->data = &from_object; + else if (__strcasestr (step->to_name, CHARSET_NAME) != NULL) + step->data = &to_object; + else + return GCONV_NOCONV; + + step->min_needed_from = MIN_NEEDED_FROM; + step->max_needed_from = MAX_NEEDED_FROM; + step->min_needed_to = MIN_NEEDED_TO; + step->max_needed_to = MAX_NEEDED_TO; + + return GCONV_OK; +} +#endif + + +/* The default destructor function does nothing in the moment and so + be define it at all. But we still provide the macro just in case + we need it some day. */ +#if DEFINE_FINI +#endif + + +/* This is the actual conversion function. */ +#ifndef FUNCTION_NAME +# define FUNCTION_NAME gconv +#endif + +int +FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data, + const char **inbuf, const char *inbufend, size_t *written, + int do_flush) +{ + struct gconv_step *next_step = step + 1; + struct gconv_step_data *next_data = data + 1; + gconv_fct fct = next_step->fct; + int status; + + /* If the function is called with no input this means we have to reset + to the initial state. The possibly partly converted input is + dropped. */ + if (do_flush) + { + /* Call the steps down the chain if there are any. */ + if (data->is_last) + status = GCONV_OK; + else + { +#ifdef EMIT_SHIFT_TO_INIT + status = GCONV_OK; + + EMIT_SHIFT_TO_INIT; + + if (status == GCONV_OK) +#endif + /* Give the modules below the same chance. */ + status = (*fct) (next_step, next_data, NULL, NULL, written, 1); + } + } + else + { + /* This variable is used to count the number of characters we + actually converted. */ + size_t converted = 0; + + /* We preserve the initial values of the pointer variables. */ + const char *inptr = *inbuf; + char *outbuf = data->outbuf; + char *outend = data->outbufend; + char *outptr; + + do + { + /* Remember the start value for this round. */ + inptr = *inbuf; + /* The outbuf buffer is empty. */ + outptr = outbuf; + + /* Save the state. */ +#ifdef SAVE_RESET_STATE + SAVE_RESET_STATE (1); +#endif + + if (FROM_DIRECTION) + /* Run the conversion loop. */ + status = FROM_LOOP ((const unsigned char **) inbuf, + (const unsigned char *) inbufend, + (unsigned char **) &outbuf, + (unsigned char *) outend, + data->statep, step->data, &converted); + else + /* Run the conversion loop. */ + status = TO_LOOP ((const unsigned char **) inbuf, + (const unsigned char *) inbufend, + (unsigned char **) &outbuf, + (unsigned char *) outend, + data->statep, step->data, &converted); + + /* If this is the last step leave the loop, there is nothgin + we can do. */ + if (data->is_last) + { + /* Store information about how many bytes are available. */ + data->outbuf = outbuf; + break; + } + + /* Write out all output which was produced. */ + if (outbuf > outptr) + { + const char *outerr = outbuf; + int result; + + result = (*fct) (next_step, next_data, &outerr, outbuf, + written, 0); + + if (result != GCONV_EMPTY_INPUT) + { + if (outerr != outbuf) + { +#ifdef RESET_INPUT_BUFFER + RESET_INPUT_BUFFER; +#else + /* We have a problem with the in on of the functions + below. Undo the conversion upto the error point. */ + size_t nstatus; + + /* Reload the pointers. */ + *inbuf = inptr; + outbuf = outptr; + + /* Reset the state. */ +# ifdef SAVE_RESET_STATE + SAVE_RESET_STATE (0); +# endif + + if (FROM_DIRECTION) + /* Run the conversion loop. */ + nstatus = FROM_LOOP ((const unsigned char **) inbuf, + (const unsigned char *) inbufend, + (unsigned char **) &outbuf, + (unsigned char *) outerr, + data->statep, step->data, + &converted); + else + /* Run the conversion loop. */ + nstatus = TO_LOOP ((const unsigned char **) inbuf, + (const unsigned char *) inbufend, + (unsigned char **) &outbuf, + (unsigned char *) outerr, + data->statep, step->data, + &converted); + + /* We must run out of output buffer space in this + rerun. */ + assert (nstatus == GCONV_FULL_OUTPUT + && outbuf == outerr); +#endif /* reset input buffer */ + } + + /* Change the status. */ + status = result; + } + else + /* All the output is consumed, we can make another run + if everything was ok. */ + if (status == GCONV_FULL_OUTPUT) + status = GCONV_OK; + } + } + while (status == GCONV_OK); + + /* Remember how many characters we converted. */ + *written += converted; + } + + return status; +} + +#undef DEFINE_INIT +#undef CHARSET_NAME +#undef DEFINE_FINI +#undef MIN_NEEDED_FROM +#undef MIN_NEEDED_TO +#undef MAX_NEEDED_FROM +#undef MAX_NEEDED_TO +#undef DEFINE_DIRECTION_OBJECTS +#undef FROM_DIRECTION +#undef EMIT_SHIFT_TO_INIT +#undef FROM_LOOP +#undef TO_LOOP +#undef RESET_STATE +#undef RESET_INPUT_BUFFER +#undef FUNCTION_NAME diff --git a/iconvdata/8bit-gap.c b/iconvdata/8bit-gap.c index a8d3c99a68..4065a6d777 100644 --- a/iconvdata/8bit-gap.c +++ b/iconvdata/8bit-gap.c @@ -19,10 +19,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <string.h> - struct gap { @@ -34,192 +31,68 @@ struct gap /* Now we can include the tables. */ #include TABLES -/* We use three objects to describe the operation mode. */ -static int from_8bit_object; -static int to_8bit_object; - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, NAME) != NULL) - step->data = &from_8bit_object; - else if (strcasestr (step->to_name, NAME) != NULL) - step->data = &to_8bit_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_8bit_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - wchar_t ch = to_ucs4[((unsigned char *) inbuf)[cnt]]; - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - const struct gap *rp = from_idx; - unsigned int ch = *((wchar_t *) (inbuf + cnt)); - char res; - - while (ch > rp->end) - ++rp; - if (ch < rp->start) - /* No valid character. */ - break; - - res = from_ucs4[ch + rp->idx]; - if (res == '\0' && ch != 0) - /* No valid character. */ - break; - - outbuf[outchars] = res; - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_8bit_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - return result; -} +#define FROM_LOOP from_gap +#define TO_LOOP to_gap +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from the 8bit charset to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = to_ucs4[*inptr]; \ + \ + if (HAS_HOLES && ch == L'\0' && *inptr != '\0') \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + ++inptr; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + const struct gap *rp = from_idx; \ + uint32_t ch = *((uint32_t *) inptr); \ + unsigned char res; \ + \ + while (ch > rp->end) \ + ++rp; \ + if (ch < rp->start) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + res = from_ucs4[ch + rp->idx]; \ + if (ch != 0 && res == '\0') \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *outptr++ = res; \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/8bit-generic.c b/iconvdata/8bit-generic.c index 19194ad068..2ea333199e 100644 --- a/iconvdata/8bit-generic.c +++ b/iconvdata/8bit-generic.c @@ -18,186 +18,56 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> -#include <string.h> - -/* We use three objects to describe the operation mode. */ -static int from_8bit_object; -static int to_8bit_object; - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, NAME) != NULL) - step->data = &from_8bit_object; - else if (strcasestr (step->to_name, NAME) != NULL) - step->data = &to_8bit_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_8bit_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - wchar_t ch = to_ucs4[((unsigned char *) inbuf)[cnt]]; - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - int ch = *((wchar_t *) (inbuf + cnt)); - - if (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0]) - || ch < 0 || (from_ucs4[ch] == '\0' && ch != 0)) - break; - - outbuf[outchars] = from_ucs4[ch]; - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_8bit_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +#define FROM_LOOP from_generic +#define TO_LOOP to_generic +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from the 8bit charset to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = to_ucs4[*inptr]; \ + \ + if (HAS_HOLES && ch == L'\0' && *inptr != '\0') \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + ++inptr; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + \ + if (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0]) \ + || (ch != 0 && from_ucs4[ch] == '\0')) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *outptr++ = from_ucs4[ch]; \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/Makefile b/iconvdata/Makefile index dd1c391c6c..69576859ec 100644 --- a/iconvdata/Makefile +++ b/iconvdata/Makefile @@ -26,8 +26,8 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10 \ T.61 ISO_6937 SJIS KOI-8 KOI8-R LATIN-GREEK LATIN-GREEK-1 \ HP-ROMAN8 EBCDIC-AT-DE EBCDIC-AT-DE-A EBCDIC-CA-FR \ - EUC-KR UHC JOHAB libJIS libKSC ISO646 BIG5 EUC-JP libGB \ - EUC-CN libCNS EUC-TW + EUC-KR UHC JOHAB libJIS libKSC BIG5 EUC-JP libGB \ + EUC-CN libCNS EUC-TW # ISO646 modules.so := $(addsuffix .so, $(modules)) @@ -211,7 +211,7 @@ endif include ../Rules .PHONY: do-iconv-test -tests: do-iconv-test +#tests: do-iconv-test do-iconv-test: run-iconv-test.sh $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) \ diff --git a/iconvdata/big5.c b/iconvdata/big5.c index a6a2580dd7..2962712167 100644 --- a/iconvdata/big5.c +++ b/iconvdata/big5.c @@ -8411,289 +8411,180 @@ static const char from_ucs4_tab13[][2] = }; -/* Direction of the transformation. */ -static int to_big5_object; -static int from_big5_object; +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "BIG5" +#define FROM_LOOP from_big5 +#define TO_LOOP to_big5 +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "BIG5") != NULL) - step->data = &from_big5_object; - else if (strcasestr (step->to_name, "BIG5") != NULL) - step->data = &to_big5_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_big5_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = inbuf[cnt]; - wchar_t ch; - - if (inchar < '\xa1' || inchar > '\xfe') - ch = (wchar_t) inchar; - else - { - /* Two-byte character. First test whether the next - character is also available. */ - int inchar2; - int idx; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - idx = (inchar - 0xa1) * 157; - inchar2 = inbuf[++cnt]; - /* See whether the second byte is in the correct - range. */ - if (inchar2 >= '\x40' && inchar2 <= '\x7e') - idx += inchar2 - 0x40; - else if (inchar2 >= '\xa1' && inchar2 <= '\xfe') - idx += 0x3f + (inchar2 - 0xa1); - else - { - /* This is illegal. */ - --cnt; - result = GCONV_ILLEGAL_INPUT; - break; - } - - /* Get the value from the table. */ - ch = big5_to_ucs[idx]; - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - int ch = *((wchar_t *) (inbuf + cnt)); - char buf[2]; - const char *cp; - - if (ch >= (sizeof (from_ucs4_tab1) - / sizeof (from_ucs4_tab1[0]))) - { - if (ch >= 0x2c7 && ch <= 0x2d9) - cp = from_ucs4_tab2[ch - 0x2c7]; - else if (ch >= 0x391 && ch <= 0x451) - cp = from_ucs4_tab3[ch - 0x391]; - else if (ch >= 0x2013 && ch <= 0x203e) - cp = from_ucs4_tab4[ch - 0x2013]; - else if (ch == 0x2103) - cp = "\xa2\x4a"; - else if (ch == 0x2105) - cp = "\xa1\xc1"; - else if (ch == 0x2109) - cp = "\xa2\x4b"; - else if (ch >= 0x2160 && ch <= 0x2169) - { - buf[0] = '\xa2'; - buf[1] = '\xb9' + (ch - 0x2160); - cp = buf; - } - else if (ch >= 0x2190 && ch <= 0x2199) - cp = from_ucs4_tab5[ch - 0x2190]; - else if (ch >= 0x221a && ch <= 0x22bf) - cp = from_ucs4_tab6[ch - 0x221a]; - else if (ch >= 0x2460 && ch <= 0x247d) - cp = from_ucs4_tab7[ch - 0x2460]; - else if (ch >= 0x2500 && ch <= 0x2642) - cp = from_ucs4_tab8[ch - 0x2500]; - else if (ch >= 0x3000 && ch <= 0x3129) - cp = from_ucs4_tab9[ch - 0x3000]; - else if (ch == 0x32a3) - cp = "\xa1\xc0"; - else if (ch >= 0x338e && ch <= 0x33d5) - cp = from_ucs4_tab10[ch - 0x338e]; - else if (ch >= 0x4e00 && ch <= 0x9fa4) - cp = from_ucs4_tab11[ch - 0x4e00]; - else if (ch == 0xfa0c) - cp = "\xc9\x4a"; - else if (ch == 0xfa0d) - cp = "\xdd\xfc"; - else if (ch >= 0xfe30 && ch <= 0xfe6b) - cp = from_ucs4_tab12[ch - 0xfe30]; - else if (ch >= 0xff01 && ch <= 0xff64) - cp = from_ucs4_tab13[ch - 0xff01]; - else - /* Illegal character. */ - break; - } - else - cp = from_ucs4_tab1[ch]; - - if (cp[0] == '\0' && ch != 0) - /* Illegal character. */ - break; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_big5_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; +/* First define the conversion function from Big5 to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch >= '\xa1' && ch <= '\xff') \ + { \ + /* Two-byte character. First test whether the next character \ + is also available. */ \ + uint32_t ch2; \ + int idx; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + idx = (ch - 0xa1) * 157; \ + ch2 = inptr[1]; \ + /* See whether the second byte is in the correct range. */ \ + if (ch2 >= '\x40' && ch2 <= '\x7e') \ + idx += ch2 - 0x40; \ + else if (ch2 >= '\xa1' && ch2 <= '\xfe') \ + idx += 0x3f + (ch2 - 0xa1); \ + else \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* Get the value from the table. */ \ + ch = big5_to_ucs[idx]; \ + \ + /* Is this character defined? */ \ + if (ch == L'\0' && *inptr != '\0') \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + else \ + ++inptr; \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + char buf[2]; \ + const char *cp; \ + \ + if (ch >= sizeof (from_ucs4_tab1) / sizeof (from_ucs4_tab1[0])) \ + switch (ch) \ + { \ + case 0x2c7 ... 0x2d9: \ + cp = from_ucs4_tab2[ch - 0x2c7]; \ + break; \ + case 0x391 ... 0x451: \ + cp = from_ucs4_tab3[ch - 0x391]; \ + break; \ + case 0x2013 ... 0x203e: \ + cp = from_ucs4_tab4[ch - 0x2013]; \ + break; \ + case 0x2103: \ + cp = "\xa2\x4a"; \ + break; \ + case 0x2105: \ + cp = "\xa1\xc1"; \ + break; \ + case 0x2109: \ + cp = "\xa2\x4b"; \ + break; \ + case 0x2160 ... 0x2169: \ + { \ + buf[0] = '\xa2'; \ + buf[1] = '\xb9' + (ch - 0x2160); \ + cp = buf; \ + } \ + break; \ + case 0x2190 ... 0x2199: \ + cp = from_ucs4_tab5[ch - 0x2190]; \ + break; \ + case 0x221a ... 0x22bf: \ + cp = from_ucs4_tab6[ch - 0x221a]; \ + break; \ + case 0x2460 ... 0x247d: \ + cp = from_ucs4_tab7[ch - 0x2460]; \ + break; \ + case 0x2500 ... 0x2642: \ + cp = from_ucs4_tab8[ch - 0x2500]; \ + break; \ + case 0x3000 ... 0x3129: \ + cp = from_ucs4_tab9[ch - 0x3000]; \ + break; \ + case 0x32a3: \ + cp = "\xa1\xc0"; \ + break; \ + case 0x338e ... 0x33d5: \ + cp = from_ucs4_tab10[ch - 0x338e]; \ + break; \ + case 0x4e00 ... 0x9fa4: \ + cp = from_ucs4_tab11[ch - 0x4e00]; \ + break; \ + case 0xfa0c: \ + cp = "\xc9\x4a"; \ + break; \ + case 0xfa0d: \ + cp = "\xdd\xfc"; \ + break; \ + case 0xfe30 ... 0xfe6b: \ + cp = from_ucs4_tab12[ch - 0xfe30]; \ + break; \ + case 0xff01 ... 0xff64: \ + cp = from_ucs4_tab13[ch - 0xff01]; \ + break; \ + default: \ + /* Illegal character. */ \ + cp = ""; \ + break; \ + } \ + else \ + cp = from_ucs4_tab1[ch]; \ + \ + if (cp[0] == '\0' && ch != 0) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* See whether there is enough room for the second byte we write. */ \ + if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend) \ + { \ + /* We have not enough room. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + *outptr++ = cp[0]; \ + if (cp[1] != '\0') \ + *outptr++ = cp[1]; \ + inptr += 4; \ + } +#include <iconv/loop.c> - if (written != NULL && data->is_last) - *written = do_write; - return result; -} +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/cns11643.c b/iconvdata/cns11643.c index 903548261b..bd1994f1d9 100644 --- a/iconvdata/cns11643.c +++ b/iconvdata/cns11643.c @@ -44,7 +44,7 @@ printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const uint16_t cns11643l2_to_ucs4_tab[] = +const uint16_t __cns11643l2_to_ucs4_tab[] = { [0x0000] = 0x4e42, [0x0001] = 0x4e5c, [0x0002] = 0x51f5, [0x0003] = 0x531a, [0x0004] = 0x5382, [0x0005] = 0x4e07, [0x0006] = 0x4e0c, [0x0007] = 0x4e47, @@ -1985,7 +1985,7 @@ const uint16_t cns11643l2_to_ucs4_tab[] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const uint16_t cns11643l14_to_ucs4_tab[] = +const uint16_t __cns11643l14_to_ucs4_tab[] = { [0x0000] = 0x4e28, [0x0001] = 0x4e36, [0x0002] = 0x4e3f, [0x0003] = 0x4e85, [0x0004] = 0x4e05, [0x0005] = 0x4e04, [0x0006] = 0x5182, [0x0007] = 0x5196, @@ -3064,7 +3064,7 @@ const uint16_t cns11643l14_to_ucs4_tab[] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643_from_ucs4_tab[][3] = +const char __cns11643_from_ucs4_tab[][3] = { [0x0000] = "\x01\x44\x21", [0x0001] = "\x01\x44\x23", [0x0003] = "\x01\x44\x24", [0x0004] = "\x0e\x21\x26", diff --git a/iconvdata/cns11643.h b/iconvdata/cns11643.h index f791d4cdb3..ccab8011ce 100644 --- a/iconvdata/cns11643.h +++ b/iconvdata/cns11643.h @@ -21,8 +21,8 @@ #include <stdint.h> /* Table for CNS 11643, plane 2 to UCS4 conversion. */ -extern const uint16_t cns11643l2_to_ucs4_tab[]; -extern const uint16_t cns11643l14_to_ucs4_tab[]; +extern const uint16_t __cns11643l2_to_ucs4_tab[]; +extern const uint16_t __cns11643l14_to_ucs4_tab[]; static inline wchar_t @@ -54,19 +54,19 @@ cns11643_to_ucs4 (const char **s, size_t avail, unsigned char offset) { if (idx > 0x2196) return UNKNOWN_10646_CHAR; - result = cns11643l1_to_ucs4_tab[idx]; + result = __cns11643l1_to_ucs4_tab[idx]; } else if ((ch - 0x21 - offset) == 2) { if (idx > 0x1de1) return UNKNOWN_10646_CHAR; - result = cns11643l2_to_ucs4_tab[idx]; + result = __cns11643l2_to_ucs4_tab[idx]; } else if ((ch - 0x21 - offset) == 0xe) { if (idx > 0x19bd) return UNKNOWN_10646_CHAR; - result = cns11643l14_to_ucs4_tab[idx]; + result = __cns11643l14_to_ucs4_tab[idx]; } else return UNKNOWN_10646_CHAR; @@ -81,21 +81,21 @@ cns11643_to_ucs4 (const char **s, size_t avail, unsigned char offset) /* Tables for the UCS4 -> CNS conversion. */ -extern const char cns11643l1_from_ucs4_tab1[][2]; -extern const char cns11643l1_from_ucs4_tab2[][2]; -extern const char cns11643l1_from_ucs4_tab3[][2]; -extern const char cns11643l1_from_ucs4_tab4[][2]; -extern const char cns11643l1_from_ucs4_tab5[][2]; -extern const char cns11643l1_from_ucs4_tab6[][2]; -extern const char cns11643l1_from_ucs4_tab7[][2]; -extern const char cns11643l1_from_ucs4_tab8[][2]; -extern const char cns11643l1_from_ucs4_tab9[][2]; -extern const char cns11643l1_from_ucs4_tab10[][2]; -extern const char cns11643l1_from_ucs4_tab11[][2]; -extern const char cns11643l1_from_ucs4_tab12[][2]; -extern const char cns11643l1_from_ucs4_tab13[][2]; -extern const char cns11643l1_from_ucs4_tab14[][2]; -extern const char cns11643_from_ucs4_tab[][3]; +extern const char __cns11643l1_from_ucs4_tab1[][2]; +extern const char __cns11643l1_from_ucs4_tab2[][2]; +extern const char __cns11643l1_from_ucs4_tab3[][2]; +extern const char __cns11643l1_from_ucs4_tab4[][2]; +extern const char __cns11643l1_from_ucs4_tab5[][2]; +extern const char __cns11643l1_from_ucs4_tab6[][2]; +extern const char __cns11643l1_from_ucs4_tab7[][2]; +extern const char __cns11643l1_from_ucs4_tab8[][2]; +extern const char __cns11643l1_from_ucs4_tab9[][2]; +extern const char __cns11643l1_from_ucs4_tab10[][2]; +extern const char __cns11643l1_from_ucs4_tab11[][2]; +extern const char __cns11643l1_from_ucs4_tab12[][2]; +extern const char __cns11643l1_from_ucs4_tab13[][2]; +extern const char __cns11643l1_from_ucs4_tab14[][2]; +extern const char __cns11643_from_ucs4_tab[][3]; static inline size_t @@ -103,120 +103,104 @@ ucs4_to_cns11643 (wchar_t wch, char *s, size_t avail) { unsigned int ch = (unsigned int) wch; char buf[2]; - const char *cp = NULL; + const char *cp = buf; int needed = 2; - if (ch < 0xa7) - cp = ""; - else if (ch < 0xf7) - cp = cns11643l1_from_ucs4_tab1[ch - 0xa7]; - else if (ch < 0x2c7) - cp = ""; - else if (ch <= 0x2d9) - cp = cns11643l1_from_ucs4_tab2[ch - 0x2c7]; - else if (ch < 0x391) - cp = ""; - else if (ch <= 0x3c9) - cp = cns11643l1_from_ucs4_tab3[ch - 0x391]; - else if (ch < 0x2013) - cp = ""; - else if (ch <= 0x203e) - cp = cns11643l1_from_ucs4_tab4[ch - 0x2013]; - else if (ch == 0x2103) - cp = "\x22\x6a"; - else if (ch == 0x2105) - cp = "\x22\x22"; - else if (ch == 0x2109) - cp = "\x22\x6b"; - else if (ch < 0x2160) - cp = ""; - else if (ch <= 0x2169) + switch (ch) { + case 0xa7 ... 0xf7: + cp = __cns11643l1_from_ucs4_tab1[ch - 0xa7]; + break; + case 0x2c7 ... 0x2d9: + cp = __cns11643l1_from_ucs4_tab2[ch - 0x2c7]; + break; + case 0x391 ... 0x3c9: + cp = __cns11643l1_from_ucs4_tab3[ch - 0x391]; + break; + case 0x2013 ... 0x203e: + cp = __cns11643l1_from_ucs4_tab4[ch - 0x2013]; + break; + case 0x2103: + cp = "\x22\x6a"; + break; + case 0x2105: + cp = "\x22\x22"; + break; + case 0x2109: + cp = "\x22\x6b"; + break; + case 0x2160 ...0x2169: buf[0] = '\x24'; buf[1] = '\x2b' + (ch - 0x2160); - cp = buf; - } - else if (ch < 0x2170) - cp = ""; - else if (ch <= 0x2179) - { + break; + case 0x2170 ... 0x2179: buf[0] = '\x26'; buf[1] = '\x35' + (ch - 0x2170); - cp = buf; - } - else if (ch < 0x2190) - cp = ""; - else if (ch <= 0x2199) - cp = cns11643l1_from_ucs4_tab5[ch - 0x2190]; - else if (ch < 0x2215) - cp = ""; - else if (ch <= 0x2267) - cp = cns11643l1_from_ucs4_tab6[ch - 0x2215]; - else if (ch == 0x22a5) - cp = "\x22\x47"; - else if (ch == 0x22bf) - cp = "\x22\x4a"; - else if (ch < 0x2400) - cp = ""; - else if (ch <= 0x2421) - cp = cns11643l1_from_ucs4_tab7[ch - 0x2400]; - else if (ch < 0x2460) - cp = ""; - else if (ch <= 0x247d) - cp = cns11643l1_from_ucs4_tab8[ch - 0x2460]; - else if (ch < 0x2500) - cp = ""; - else if (ch <= 0x2642) - cp = cns11643l1_from_ucs4_tab9[ch - 0x2500]; - else if (ch < 0x3000) - cp = ""; - else if (ch <= 0x3029) - cp = cns11643l1_from_ucs4_tab10[ch - 0x3000]; - else if (ch == 0x30fb) - cp = "\x21\x26"; - else if (ch < 0x3105) - cp = ""; - else if (ch <= 0x3129) - { + break; + case 0x2190 ... 0x2199: + cp = __cns11643l1_from_ucs4_tab5[ch - 0x2190]; + break; + case 0x2215 ... 0x2267: + cp = __cns11643l1_from_ucs4_tab6[ch - 0x2215]; + break; + case 0x22a5: + cp = "\x22\x47"; + break; + case 0x22bf: + cp = "\x22\x4a"; + break; + case 0x2400 ... 0x2421: + cp = __cns11643l1_from_ucs4_tab7[ch - 0x2400]; + break; + case 0x2460 ... 0x247d: + cp = __cns11643l1_from_ucs4_tab8[ch - 0x2460]; + break; + case 0x2500 ... 0x2642: + cp = __cns11643l1_from_ucs4_tab9[ch - 0x2500]; + case 0x3000 ... 0x3029: + cp = __cns11643l1_from_ucs4_tab10[ch - 0x3000]; + break; + case 0x30fb: + cp = "\x21\x26"; + break; + case 0x3105 ... 0x3129: buf[0] = '\x25'; buf[1] = '\x26' + (ch - 0x3105); - cp = buf; - } - else if (ch == 0x32a3) - cp = "\x22\x21"; - else if (ch < 0x338e) - cp = ""; - else if (ch <= 0x33d5) - cp = cns11643l1_from_ucs4_tab11[ch - 0x338e]; - else if (ch < 0x4e00) - cp = ""; - else if (ch <= 0x9f9c) - { - cp = cns11643l1_from_ucs4_tab12[ch - 0x4e00]; + break; + case 0x32a3: + cp = "\x22\x21"; + break; + case 0x338e ... 0x33d5: + cp = __cns11643l1_from_ucs4_tab11[ch - 0x338e]; + break; + case 0x4e00 ... 0x9f9c: + cp = __cns11643l1_from_ucs4_tab12[ch - 0x4e00]; if (cp[0] == '\0') { /* Let's try the other planes. */ needed = 3; - cp = cns11643_from_ucs4_tab[ch - 0x4e00]; + cp = __cns11643_from_ucs4_tab[ch - 0x4e00]; } + break; + case 0xfe30 ... 0xfe6b: + cp = __cns11643l1_from_ucs4_tab13[ch - 0xfe30]; + break; + case 0xff01 ... 0xff5d: + cp = __cns11643l1_from_ucs4_tab14[ch - 0xff01]; + break; + case 0xffe0: + cp = "\x22\x66"; + break; + case 0xffe1: + cp = "\x22\x67"; + break; + case 0xffe5: + cp = "\x22\x64"; + break; + default: + cp = ""; } - else if (ch < 0xfe30) - cp = ""; - else if (ch <= 0xfe6b) - cp = cns11643l1_from_ucs4_tab13[ch - 0xfe30]; - else if (ch < 0xff01) - cp = ""; - else if (ch <= 0xff5d) - cp = cns11643l1_from_ucs4_tab14[ch - 0xff01]; - else if (ch == 0xffe0) - cp = "\x22\x66"; - else if (ch == 0xffe1) - cp = "\x22\x67"; - else if (ch == 0xffe5) - cp = "\x22\x64"; - else - cp = ""; if (cp[0] == '\0') return UNKNOWN_10646_CHAR; diff --git a/iconvdata/cns11643l1.c b/iconvdata/cns11643l1.c index 730fb550ab..d106b3d34c 100644 --- a/iconvdata/cns11643l1.c +++ b/iconvdata/cns11643l1.c @@ -45,7 +45,7 @@ printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const uint16_t cns11643l1_to_ucs4_tab[] = +const uint16_t __cns11643l1_to_ucs4_tab[] = { [0x0000] = 0x3000, [0x0001] = 0xff0c, [0x0002] = 0x3001, [0x0003] = 0x3002, [0x0004] = 0xff0e, [0x0005] = 0x30fb, [0x0006] = 0xff1b, [0x0007] = 0xff1a, @@ -1517,7 +1517,7 @@ const uint16_t cns11643l1_to_ucs4_tab[] = /* Some Latin1 characters, starting at U+00a7. */ -const char cns11643l1_from_ucs4_tab1[][2] = +const char __cns11643l1_from_ucs4_tab1[][2] = { [0x00] = "\x21\x70", [0x09] = "\x22\x78", [0x0a] = "\x22\x34", [0x10] = "\x21\x31", [0x30] = "\x22\x32", [0x50] = "\x22\x33" @@ -1525,7 +1525,7 @@ const char cns11643l1_from_ucs4_tab1[][2] = /* Some phonetic modifiers, starting at U+02c7. */ -const char cns11643l1_from_ucs4_tab2[][2] = +const char __cns11643l1_from_ucs4_tab2[][2] = { [0x00] = "\x25\x6f", [0x02] = "\x25\x6d", [0x03] = "\x25\x6e", [0x04] = "\x25\x70", [0x12] = "\x25\x6c" @@ -1552,7 +1552,7 @@ const char cns11643l1_from_ucs4_tab2[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab3[][2] = +const char __cns11643l1_from_ucs4_tab3[][2] = { [0x0000] = "\x24\x75", [0x0001] = "\x24\x76", [0x0002] = "\x24\x77", [0x0003] = "\x24\x78", [0x0004] = "\x24\x79", [0x0005] = "\x24\x7a", @@ -1593,7 +1593,7 @@ const char cns11643l1_from_ucs4_tab3[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab4[][2] = +const char __cns11643l1_from_ucs4_tab4[][2] = { [0x0000] = "\x21\x39", [0x0001] = "\x21\x37", [0x0003] = "\x22\x5d", [0x0005] = "\x21\x64", [0x0006] = "\x21\x65", [0x0009] = "\x21\x66", @@ -1603,7 +1603,7 @@ const char cns11643l1_from_ucs4_tab4[][2] = }; -const char cns11643l1_from_ucs4_tab5[][2] = +const char __cns11643l1_from_ucs4_tab5[][2] = { [0x00] = "\x22\x58", [0x01] = "\x22\x55", [0x02] = "\x22\x57", [0x03] = "\x22\x56", [0x06] = "\x22\x59", [0x07] = "\x22\x5a", @@ -1631,7 +1631,7 @@ const char cns11643l1_from_ucs4_tab5[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab6[][2] = +const char __cns11643l1_from_ucs4_tab6[][2] = { [0x0000] = "\x22\x61", [0x0005] = "\x22\x35", [0x0009] = "\x22\x3c", [0x000a] = "\x22\x49", [0x000b] = "\x22\x48", [0x0014] = "\x22\x45", @@ -1661,7 +1661,7 @@ const char cns11643l1_from_ucs4_tab6[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab7[][2] = +const char __cns11643l1_from_ucs4_tab7[][2] = { [0x0000] = "\x42\x21", [0x0001] = "\x42\x22", [0x0002] = "\x42\x23", [0x0003] = "\x42\x24", [0x0004] = "\x42\x25", [0x0005] = "\x42\x26", @@ -1697,7 +1697,7 @@ const char cns11643l1_from_ucs4_tab7[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab8[][2] = +const char __cns11643l1_from_ucs4_tab8[][2] = { [0x0000] = "\x26\x21", [0x0001] = "\x26\x22", [0x0002] = "\x26\x23", [0x0003] = "\x26\x24", [0x0004] = "\x26\x25", [0x0005] = "\x26\x26", @@ -1729,7 +1729,7 @@ const char cns11643l1_from_ucs4_tab8[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab9[][2] = +const char __cns11643l1_from_ucs4_tab9[][2] = { [0x0000] = "\x23\x39", [0x0002] = "\x23\x3a", [0x000c] = "\x23\x3c", [0x0010] = "\x23\x3d", [0x0014] = "\x23\x3e", [0x0018] = "\x23\x3f", @@ -1774,7 +1774,7 @@ const char cns11643l1_from_ucs4_tab9[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab10[][2] = +const char __cns11643l1_from_ucs4_tab10[][2] = { [0x0000] = "\x21\x21", [0x0001] = "\x21\x23", [0x0002] = "\x21\x24", [0x0003] = "\x21\x71", [0x0008] = "\x21\x52", [0x0009] = "\x21\x53", @@ -1809,7 +1809,7 @@ const char cns11643l1_from_ucs4_tab10[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab11[][2] = +const char __cns11643l1_from_ucs4_tab11[][2] = { [0x0000] = "\x22\x75", [0x0001] = "\x22\x76", [0x000e] = "\x22\x70", [0x000f] = "\x22\x71", [0x0010] = "\x22\x72", [0x0013] = "\x22\x74", @@ -1838,7 +1838,7 @@ const char cns11643l1_from_ucs4_tab11[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab12[][2] = +const char __cns11643l1_from_ucs4_tab12[][2] = { [0x0000] = "\x44\x21", [0x0001] = "\x44\x23", [0x0003] = "\x44\x24", [0x0008] = "\x44\x37", [0x0009] = "\x44\x35", [0x000a] = "\x44\x38", @@ -3667,7 +3667,7 @@ const char cns11643l1_from_ucs4_tab12[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab13[][2] = +const char __cns11643l1_from_ucs4_tab13[][2] = { [0x0000] = "\x21\x2b", [0x0001] = "\x21\x36", [0x0002] = "\x21\x38", [0x0005] = "\x21\x40", [0x0006] = "\x21\x41", [0x0007] = "\x21\x44", @@ -3709,7 +3709,7 @@ const char cns11643l1_from_ucs4_tab13[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char cns11643l1_from_ucs4_tab14[][2] = +const char __cns11643l1_from_ucs4_tab14[][2] = { [0x0000] = "\x21\x2a", [0x0002] = "\x21\x6c", [0x0003] = "\x22\x63", [0x0004] = "\x22\x68", [0x0005] = "\x21\x6d", [0x0007] = "\x21\x3e", diff --git a/iconvdata/cns11643l1.h b/iconvdata/cns11643l1.h index 4f9d08513d..aa78c26d6c 100644 --- a/iconvdata/cns11643l1.h +++ b/iconvdata/cns11643l1.h @@ -19,9 +19,10 @@ Boston, MA 02111-1307, USA. */ #include <stdint.h> +#include <gconv.h> /* Table for CNS 11643, plane 1 to UCS4 conversion. */ -extern const uint16_t cns11643l1_to_ucs4_tab[]; +extern const uint16_t __cns11643l1_to_ucs4_tab[]; static inline wchar_t @@ -47,25 +48,25 @@ cns11643l1_to_ucs4 (const char **s, size_t avail, unsigned char offset) (*s) += 2; - return cns11643l1_to_ucs4_tab[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR); + return __cns11643l1_to_ucs4_tab[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR); } /* Tables for the UCS4 -> CNS conversion. */ -extern const char cns11643l1_from_ucs4_tab1[][2]; -extern const char cns11643l1_from_ucs4_tab2[][2]; -extern const char cns11643l1_from_ucs4_tab3[][2]; -extern const char cns11643l1_from_ucs4_tab4[][2]; -extern const char cns11643l1_from_ucs4_tab5[][2]; -extern const char cns11643l1_from_ucs4_tab6[][2]; -extern const char cns11643l1_from_ucs4_tab7[][2]; -extern const char cns11643l1_from_ucs4_tab8[][2]; -extern const char cns11643l1_from_ucs4_tab9[][2]; -extern const char cns11643l1_from_ucs4_tab10[][2]; -extern const char cns11643l1_from_ucs4_tab11[][2]; -extern const char cns11643l1_from_ucs4_tab12[][2]; -extern const char cns11643l1_from_ucs4_tab13[][2]; -extern const char cns11643l1_from_ucs4_tab14[][2]; +extern const char __cns11643l1_from_ucs4_tab1[][2]; +extern const char __cns11643l1_from_ucs4_tab2[][2]; +extern const char __cns11643l1_from_ucs4_tab3[][2]; +extern const char __cns11643l1_from_ucs4_tab4[][2]; +extern const char __cns11643l1_from_ucs4_tab5[][2]; +extern const char __cns11643l1_from_ucs4_tab6[][2]; +extern const char __cns11643l1_from_ucs4_tab7[][2]; +extern const char __cns11643l1_from_ucs4_tab8[][2]; +extern const char __cns11643l1_from_ucs4_tab9[][2]; +extern const char __cns11643l1_from_ucs4_tab10[][2]; +extern const char __cns11643l1_from_ucs4_tab11[][2]; +extern const char __cns11643l1_from_ucs4_tab12[][2]; +extern const char __cns11643l1_from_ucs4_tab13[][2]; +extern const char __cns11643l1_from_ucs4_tab14[][2]; static inline size_t @@ -73,110 +74,95 @@ ucs4_to_cns11643l1 (wchar_t wch, char *s, size_t avail) { unsigned int ch = (unsigned int) wch; char buf[2]; - const char *cp = NULL; - - if (ch < 0xa7) - cp = ""; - else if (ch < 0xf7) - cp = cns11643l1_from_ucs4_tab1[ch - 0xa7]; - else if (ch < 0x2c7) - cp = ""; - else if (ch <= 0x2d9) - cp = cns11643l1_from_ucs4_tab2[ch - 0x2c7]; - else if (ch < 0x391) - cp = ""; - else if (ch <= 0x3c9) - cp = cns11643l1_from_ucs4_tab3[ch - 0x391]; - else if (ch < 0x2013) - cp = ""; - else if (ch <= 0x203e) - cp = cns11643l1_from_ucs4_tab4[ch - 0x2013]; - else if (ch == 0x2103) - cp = "\x22\x6a"; - else if (ch == 0x2105) - cp = "\x22\x22"; - else if (ch == 0x2109) - cp = "\x22\x6b"; - else if (ch < 0x2160) - cp = ""; - else if (ch <= 0x2169) + const char *cp = buf; + + switch (ch) { + case 0xa7 ... 0xf7: + cp = __cns11643l1_from_ucs4_tab1[ch - 0xa7]; + break; + case 0x2c7 ... 0x2d9: + cp = __cns11643l1_from_ucs4_tab2[ch - 0x2c7]; + break; + case 0x391 ... 0x3c9: + cp = __cns11643l1_from_ucs4_tab3[ch - 0x391]; + case 0x2013 ... 0x203e: + cp = __cns11643l1_from_ucs4_tab4[ch - 0x2013]; + case 0x2103: + cp = "\x22\x6a"; + break; + case 0x2105: + cp = "\x22\x22"; + break; + case 0x2109: + cp = "\x22\x6b"; + break; + case 0x2160 ... 0x2169: buf[0] = '\x24'; buf[1] = '\x2b' + (ch - 0x2160); - cp = buf; - } - else if (ch < 0x2170) - cp = ""; - else if (ch <= 0x2179) - { + break; + case 0x2170 ... 0x2179: buf[0] = '\x26'; buf[1] = '\x35' + (ch - 0x2170); - cp = buf; - } - else if (ch < 0x2190) - cp = ""; - else if (ch <= 0x2199) - cp = cns11643l1_from_ucs4_tab5[ch - 0x2190]; - else if (ch < 0x2215) - cp = ""; - else if (ch <= 0x2267) - cp = cns11643l1_from_ucs4_tab6[ch - 0x2215]; - else if (ch == 0x22a5) - cp = "\x22\x47"; - else if (ch == 0x22bf) - cp = "\x22\x4a"; - else if (ch < 0x2400) - cp = ""; - else if (ch <= 0x2421) - cp = cns11643l1_from_ucs4_tab7[ch - 0x2400]; - else if (ch < 0x2460) - cp = ""; - else if (ch <= 0x247d) - cp = cns11643l1_from_ucs4_tab8[ch - 0x2460]; - else if (ch < 0x2500) - cp = ""; - else if (ch <= 0x2642) - cp = cns11643l1_from_ucs4_tab9[ch - 0x2500]; - else if (ch < 0x3000) - cp = ""; - else if (ch <= 0x3029) - cp = cns11643l1_from_ucs4_tab10[ch - 0x3000]; - else if (ch == 0x30fb) - cp = "\x21\x26"; - else if (ch < 0x3105) - cp = ""; - else if (ch <= 0x3129) - { + break; + case 0x2190 ...0x2199: + cp = __cns11643l1_from_ucs4_tab5[ch - 0x2190]; + break; + case 0x2215 ... 0x2267: + cp = __cns11643l1_from_ucs4_tab6[ch - 0x2215]; + break; + case 0x22a5: + cp = "\x22\x47"; + break; + case 0x22bf: + cp = "\x22\x4a"; + break; + case 0x2400 ... 0x2421: + cp = __cns11643l1_from_ucs4_tab7[ch - 0x2400]; + break; + case 0x2460 ... 0x247d: + cp = __cns11643l1_from_ucs4_tab8[ch - 0x2460]; + break; + case 0x2500 ... 0x2642: + cp = __cns11643l1_from_ucs4_tab9[ch - 0x2500]; + break; + case 0x3000 ... 0x3029: + cp = __cns11643l1_from_ucs4_tab10[ch - 0x3000]; + break; + case 0x30fb: + cp = "\x21\x26"; + break; + case 0x3105 ... 0x3129: buf[0] = '\x25'; buf[1] = '\x26' + (ch - 0x3105); - cp = buf; + break; + case 0x32a3: + cp = "\x22\x21"; + break; + case 0x338e ... 0x33d5: + cp = __cns11643l1_from_ucs4_tab11[ch - 0x338e]; + break; + case 0x4e00 ... 0x9f9c: + cp = __cns11643l1_from_ucs4_tab12[ch - 0x4e00]; + break; + case 0xfe30 ... 0xfe6b: + cp = __cns11643l1_from_ucs4_tab13[ch - 0xfe30]; + break; + case 0xff01 ... 0xff5d: + cp = __cns11643l1_from_ucs4_tab14[ch - 0xff01]; + break; + case 0xffe0: + cp = "\x22\x66"; + break; + case 0xffe1: + cp = "\x22\x67"; + break; + case 0xffe5: + cp = "\x22\x64"; + break; + default: + buf[0] = '\0'; } - else if (ch == 0x32a3) - cp = "\x22\x21"; - else if (ch < 0x338e) - cp = ""; - else if (ch <= 0x33d5) - cp = cns11643l1_from_ucs4_tab11[ch - 0x338e]; - else if (ch < 0x4e00) - cp = ""; - else if (ch <= 0x9f9c) - cp = cns11643l1_from_ucs4_tab12[ch - 0x4e00]; - else if (ch < 0xfe30) - cp = ""; - else if (ch <= 0xfe6b) - cp = cns11643l1_from_ucs4_tab13[ch - 0xfe30]; - else if (ch < 0xff01) - cp = ""; - else if (ch <= 0xff5d) - cp = cns11643l1_from_ucs4_tab14[ch - 0xff01]; - else if (ch == 0xffe0) - cp = "\x22\x66"; - else if (ch == 0xffe1) - cp = "\x22\x67"; - else if (ch == 0xffe5) - cp = "\x22\x64"; - else - cp = ""; if (cp[0] == '\0') return UNKNOWN_10646_CHAR; diff --git a/iconvdata/ebcdic-at-de-a.c b/iconvdata/ebcdic-at-de-a.c index 7251490ae7..654bdf87fd 100644 --- a/iconvdata/ebcdic-at-de-a.c +++ b/iconvdata/ebcdic-at-de-a.c @@ -1,5 +1,5 @@ /* Conversion from and to EBCDIC-AT-DE-A. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,12 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> + +/* Get the conversion table. */ #include <ebcdic-at-de-a.h> -#define NAME "EBCDIC-AT-DE-A" + +#define CHARSET_NAME "EBCDIC-AT-DE-A" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/ebcdic-at-de.c b/iconvdata/ebcdic-at-de.c index d9168fcc1d..ab718851d9 100644 --- a/iconvdata/ebcdic-at-de.c +++ b/iconvdata/ebcdic-at-de.c @@ -1,5 +1,5 @@ /* Conversion from and to EBCDIC-AT-DE. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,12 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> + +/* Get the conversion table. */ #include <ebcdic-at-de.h> -#define NAME "EBCDIC-AT-DE" + +#define CHARSET_NAME "EBCDIC-AT-DE" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/ebcdic-ca-fr.c b/iconvdata/ebcdic-ca-fr.c index a42914e50e..91cf5aa388 100644 --- a/iconvdata/ebcdic-ca-fr.c +++ b/iconvdata/ebcdic-ca-fr.c @@ -1,5 +1,5 @@ /* Conversion from and to EBCDIC-CA-FR. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,12 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> + +/* Get the conversion table. */ #include <ebcdic-ca-fr.h> -#define NAME "EBCDIC-CA-FR" + +#define CHARSET_NAME "EBCDIC-CA-FR" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/euccn.c b/iconvdata/euccn.c index f683836ff7..90e82cb41e 100644 --- a/iconvdata/euccn.c +++ b/iconvdata/euccn.c @@ -18,262 +18,124 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> -#include <stdint.h> -#include <string.h> -#include <wchar.h> #include <gb2312.h> +#include <stdint.h> -/* Direction of the transformation. */ -static int to_euccn_object; -static int from_euccn_object; - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "EUC-CN") != NULL) - step->data = &from_euccn_object; - else if (strcasestr (step->to_name, "EUC-CN") != NULL) - step->data = &to_euccn_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_euccn_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = (unsigned char) inbuf[cnt]; - wchar_t ch; - - if (inchar <= 0x7f) - ch = (wchar_t) inchar; - else if ((inchar <= 0xa0 || inchar > 0xfe) - && inchar != 0x8e && inchar != 0x8f) - /* This is illegal. */ - ch = L'\0'; - else - { - /* Two or more byte character. First test whether the - next character is also available. */ - const char *endp; - int inchar2; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = (unsigned char) inbuf[++cnt]; - - /* All second bytes of a multibyte character must be - >= 0xa1. */ - if (inchar2 < 0xa1) - { - /* This is an illegal character. */ - --cnt; - result = GCONV_ILLEGAL_INPUT; - break; - } - - /* This is code set 1: GB 2312-80. */ - endp = &inbuf[cnt - 1]; - - ch = gb2312_to_ucs4 (&endp, 2, 0x80); - if (ch != L'\0') - ++cnt; - - if (ch == UNKNOWN_10646_CHAR) - ch = L'\0'; - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - wchar_t ch = *((wchar_t *) (inbuf + cnt)); - - if (ch <= L'\x7f') - /* It's plain ASCII. */ - outbuf[outchars] = ch; - else - { - /* Try the JIS character sets. */ - size_t found; - - found = ucs4_to_gb2312 (ch, &outbuf[outchars], - (data->outbufsize - - outchars)); - if (found > 0) - { - /* It's a GB 2312 character, adjust it for - EUC-CN. */ - outbuf[outchars++] += 0x80; - outbuf[outchars] += 0x80; - } - else if (found == 0) - { - /* We ran out of space. */ - extra = 2; - break; - } - else - /* Illegal character. */ - break; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_euccn_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "EUC-CN" +#define FROM_LOOP from_euc_cn +#define TO_LOOP to_euc_cn +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from ISO 8859-1 to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch <= 0x7f) \ + ++inptr; \ + else \ + if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two or more byte character. First test whether the \ + next character is also available. */ \ + const char *endp; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. Store \ + the intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch = inptr[1]; \ + \ + /* All second bytes of a multibyte character must be >= 0xa1. */ \ + if (ch < 0xa1) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* This is code set 1: GB 2312-80. */ \ + endp = inptr; \ + \ + ch = gb2312_to_ucs4 (&endp, 2, 0x80); \ + if (ch == UNKNOWN_10646_CHAR) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + \ + if (ch <= L'\x7f') \ + /* It's plain ASCII. */ \ + *outptr++ = (unsigned char) ch; \ + else \ + { \ + size_t found; \ + \ + found = ucs4_to_gb2312 (ch, outptr, \ + (NEED_LENGTH_TEST \ + ? outend - outptr : MAX_NEEDED_OUTPUT)); \ + if (!NEED_LENGTH_TEST || found != 0) \ + { \ + if (found == UNKNOWN_10646_CHAR) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* It's a GB 2312 character, adjust it for EUC-CN. */ \ + *outptr++ += 0x80; \ + *outptr++ += 0x80; \ + } \ + else \ + { \ + /* We ran out of space. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + } \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/eucjp.c b/iconvdata/eucjp.c index e6a71cc791..24ebed94ec 100644 --- a/iconvdata/eucjp.c +++ b/iconvdata/eucjp.c @@ -18,306 +18,190 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <string.h> -#include <wchar.h> +#include <gconv.h> #include <jis0201.h> #include <jis0208.h> #include <jis0212.h> -/* Direction of the transformation. */ -static int to_eucjp_object; -static int from_eucjp_object; - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "EUC-JP") != NULL) - step->data = &from_eucjp_object; - else if (strcasestr (step->to_name, "EUC-JP") != NULL) - step->data = &to_eucjp_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_eucjp_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = (unsigned char) inbuf[cnt]; - wchar_t ch; - - if (inchar <= 0x7f) - ch = (wchar_t) inchar; - else if ((inchar <= 0xa0 || inchar > 0xfe) - && inchar != 0x8e && inchar != 0x8f) - /* This is illegal. */ - ch = L'\0'; - else - { - /* Two or more byte character. First test whether the - next character is also available. */ - int inchar2; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = (unsigned char) inbuf[++cnt]; - - /* All second bytes of a multibyte character must be - >= 0xa1. */ - if (inchar2 < 0xa1) - { - /* This is an illegal character. */ - --cnt; - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (inchar == '\x8e') - /* This is code set 2: half-width katakana. */ - ch = jisx0201_to_ucs4 (inchar2); - else if (inchar == '\x8f') - { - /* This is code set 3: JIS X 0212-1990. */ - const char *endp = &inbuf[cnt]; - - ch = jisx0212_to_ucs4 (&endp, 1 + inchars - cnt, - 0x80); - cnt = endp - inbuf; - } - else - { - /* This is code set 1: JIS X 0208. */ - const char *endp = &inbuf[cnt - 1]; - - ch = jisx0208_to_ucs4 (&endp, 2 + inchars - cnt, - 0x80); - if (ch != L'\0') - ++cnt; - } - - if (ch == UNKNOWN_10646_CHAR) - ch = L'\0'; - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - wchar_t ch = *((wchar_t *) (inbuf + cnt)); - - if (ch <= L'\x7f') - /* It's plain ASCII. */ - outbuf[outchars] = ch; - else - { - /* Try the JIS character sets. */ - size_t found; - - found = ucs4_to_jisx0201 (ch, &outbuf[outchars]); - - if (found == UNKNOWN_10646_CHAR) - { - /* No JIS 0201 character. */ - found = ucs4_to_jisx0208 (ch, &outbuf[outchars], - (data->outbufsize - - outchars)); - if (found == 0) - { - /* We ran out of space. */ - extra = 2; - break; - } - else if (found != UNKNOWN_10646_CHAR) - { - /* It's a JIS 0208 character, adjust it for - EUC-JP. */ - outbuf[outchars++] += 0x80; - outbuf[outchars] += 0x80; - } - else - { - /* No JIS 0208 character. */ - found = ucs4_to_jisx0212 (ch, &outbuf[outchars], - (data->outbufsize - - outchars)); - - if (found == 0) - { - /* We ran out of space. */ - extra = 2; - break; - } - else if (found != UNKNOWN_10646_CHAR) - { - /* It's a JIS 0212 character, adjust it for - EUC-JP. */ - outbuf[outchars++] += 0x80; - outbuf[outchars] += 0x80; - } - else - /* Illegal character. */ - break; - } - } - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_eucjp_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "EUC-JP" +#define FROM_LOOP from_euc_jp +#define TO_LOOP to_euc_jp +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 3 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from EUC-JP to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch <= 0x7f) \ + ++inptr; \ + else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two or more byte character. First test whether the next \ + character is also available. */ \ + int ch2; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. Store the \ + intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + \ + /* All second bytes of a multibyte character must be >= 0xa1. */ \ + if (ch2 < 0xa1) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + if (ch == 0x8e) \ + { \ + /* This is code set 2: half-width katakana. */ \ + ch = jisx0201_to_ucs4 (ch2); \ + inptr += 2; \ + } \ + else \ + { \ + const unsigned char *endp; \ + \ + if (ch == 0x8f) \ + { \ + /* This is code set 3: JIS X 0212-1990. */ \ + endp = inptr + 1; \ + \ + ch = jisx0212_to_ucs4 (&endp, \ + NEED_LENGTH_TEST ? inend - endp : 2, \ + 0x80); \ + } \ + else \ + { \ + /* This is code set 1: JIS X 0208. */ \ + endp = inptr; \ + \ + ch = jisx0208_to_ucs4 (&endp, \ + NEED_LENGTH_TEST ? inend - inptr : 2, \ + 0x80); \ + } \ + \ + if (NEED_LENGTH_TEST && ch == 0) \ + { \ + /* Not enough input available. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + if (ch == UNKNOWN_10646_CHAR) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + inptr = endp; \ + } \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + \ + if (ch <= 0x7f) \ + /* It's plain ASCII. */ \ + *outptr++ = ch; \ + else \ + { \ + /* Try the JIS character sets. */ \ + size_t found; \ + \ + /* See whether we have room for at least two characters. */ \ + if (NEED_LENGTH_TEST && outptr + 1 >= outend) \ + { \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + found = ucs4_to_jisx0201 (ch, outptr + 1); \ + if (found != UNKNOWN_10646_CHAR) \ + { \ + /* Yes, it's a JIS 0201 character. Store the shift byte. */ \ + *outptr = 0x8e; \ + outptr += 2; \ + } \ + else \ + { \ + /* No JIS 0201 character. */ \ + found = ucs4_to_jisx0208 (ch, outptr, 2); \ + /* Please note that we always have enough room for the output. */ \ + if (found != UNKNOWN_10646_CHAR) \ + { \ + /* It's a JIS 0208 character, adjust it for EUC-JP. */ \ + *outptr++ += 0x80; \ + *outptr++ += 0x80; \ + } \ + else \ + { \ + /* No JIS 0208 character. */ \ + found = ucs4_to_jisx0212 (ch, outptr + 1, \ + (NEED_LENGTH_TEST \ + ? outend - outptr - 1 : 2)); \ + \ + if (found == 0) \ + { \ + /* We ran out of space. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + else if (found != UNKNOWN_10646_CHAR) \ + { \ + /* It's a JIS 0212 character, adjust it for EUC-JP. */ \ + *outptr++ = 0x8f; \ + *outptr++ += 0x80; \ + *outptr++ += 0x80; \ + } \ + else \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + } \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/euckr.c b/iconvdata/euckr.c index 2ad9478729..50e4b40838 100644 --- a/iconvdata/euckr.c +++ b/iconvdata/euckr.c @@ -1,7 +1,8 @@ /* Mapping tables for EUC-KR handling. Copyright (C) 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Jungshik Shin <jshin@pantheon.yale.edu>, 1998. + Contributed by Jungshik Shin <jshin@pantheon.yale.edu> + and Ulrich Drepper <drepper@cygnus.com>, 1998. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -18,276 +19,142 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <wchar.h> #include <ksc5601.h> -/* Direction of the transformation. */ -static int to_euckr_object; -static int from_euckr_object; - static inline void -euckr_from_ucs4(wchar_t ch, unsigned char *cp) +euckr_from_ucs4 (uint32_t ch, unsigned char *cp) { if (ch > 0x7f) { - uint16_t idx=0; + uint16_t idx = 0; if (ucs4_to_ksc5601 (ch, &idx)) idx |= 0x8080; - *cp = (unsigned char) (idx/256); - *(cp+1) = (unsigned char) (idx & 0xff) ; + cp[0] = (unsigned char) (idx / 256); + cp[1] = (unsigned char) (idx & 0xff); } - /* think about 0x5c ; '\' */ + /* XXX Think about 0x5c ; '\'. */ else { - *cp = (unsigned char) (0x7f & ch) ; - *(cp+1) = (unsigned char) 0; + cp[0] = (unsigned char) ch; + cp[1] = '\0'; } } -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "EUC-KR") != NULL) - step->data = &from_euckr_object; - else if (strcasestr (step->to_name, "EUC-KR") != NULL) - step->data = &to_euckr_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_euckr_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = (unsigned char) inbuf[cnt]; - wchar_t ch; - - /* - half-width Korean Currency WON sign - - if (inchar == 0x5c) - ch = 0x20a9; - else if (inchar <= 0x7f) - ch = (wchar_t) inchar; - */ - - if (inchar <= 0x7f) - ch = (wchar_t) inchar; - - -/* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are user-defined areas */ - - else if ( inchar <= 0xa0 || inchar > 0xfe || inchar == 0xc9) - /* This is illegal. */ - ch = L'\0'; - else - { - /* Two-byte character. First test whether the next - character is also available. */ - int inchar2; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = (unsigned char) inbuf[++cnt]; - - ch = ksc5601_to_ucs4 ((uint16_t) (inchar * 256 + inchar2) - & 0x7f7f); - if (ch == UNKNOWN_10646_CHAR) - ch = L'\0'; - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - wchar_t ch = *((wchar_t *) (inbuf + cnt)); - unsigned char cp[2]; - -/* decomposing Hangul syllables not available in KS C 5601 into Jamos - should be considered either here or in euckr_from_ucs4() */ - - euckr_from_ucs4(ch,cp) ; - - if (cp[0] == '\0' && ch != 0) - /* Illegal character. */ - break; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_euckr_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "EUC-KR" +#define FROM_LOOP from_euc_kr +#define TO_LOOP to_euc_kr +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from EUC-KR to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + /* Half-width Korean Currency WON sign \ + \ + if (inchar == 0x5c) \ + ch = 0x20a9; \ + else if (inchar <= 0x7f) \ + ch = (wchar_t) inchar; \ + */ \ + \ + if (ch <= 0x7f) \ + /* Plain ASCII. */ \ + ++inptr; \ + /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \ + user-defined areas. */ \ + else if (ch <= 0xa0 || ch > 0xfe || ch == 0xc9) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two-byte character. First test whether the next character \ + is also available. */ \ + int ch2; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + \ + if (ch2 < 0xa1 || ch2 >= 0xfe \ + || ((ch = ksc5601_to_ucs4 ((uint16_t) (ch * 256 + ch2) & 0x7f7f)) \ + == UNKNOWN_10646_CHAR)) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + unsigned char cp[2]; \ + \ + /* Decomposing Hangul syllables not available in KS C 5601 into \ + Jamos should be considered either here or in euckr_from_ucs4() */ \ + euckr_from_ucs4 (ch, cp) ; \ + \ + if (cp[0] == '\0' && ch != 0) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *outptr++ = cp[0]; \ + /* Now test for a possible second byte and write this if possible. */ \ + if (cp[1] != '\0') \ + { \ + if (NEED_LENGTH_TEST && outptr >= outend) \ + { \ + /* The result does not fit into the buffer. */ \ + --outptr; \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + *outptr++ = cp[1]; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/euctw.c b/iconvdata/euctw.c index fd422c1fb0..406dd67f29 100644 --- a/iconvdata/euctw.c +++ b/iconvdata/euctw.c @@ -18,302 +18,171 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <string.h> -#include <wchar.h> #include <cns11643l1.h> #include <cns11643.h> -/* Direction of the transformation. */ -static int to_euctw_object; -static int from_euctw_object; - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "EUC-TW") != NULL) - step->data = &from_euctw_object; - else if (strcasestr (step->to_name, "EUC-TW") != NULL) - step->data = &to_euctw_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_euctw_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = (unsigned char) inbuf[cnt]; - wchar_t ch; - - if (inchar <= 0x7f) - ch = (wchar_t) inchar; - else if ((inchar <= 0xa0 || inchar > 0xfe) - && inchar != 0x8e) - /* This is illegal. */ - ch = L'\0'; - else - { - /* Two or more byte character. First test whether the - next character is also available. */ - int inchar2; - - if (cnt + 1 + (inchar == 0x8e ? 2 : 0) >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = (unsigned char) inbuf[++cnt]; - - /* All second bytes of a multibyte character must be - >= 0xa1. */ - if (inchar2 < 0xa1 && inchar2 == 0xff) - { - /* This is an illegal character. */ - --cnt; - result = GCONV_ILLEGAL_INPUT; - break; - } - - if (inchar == '\x8e') - { - /* This is code set 2: CNS 11643, planes 1 to 16. */ - const char *endp = &inbuf[cnt]; - - ch = cns11643_to_ucs4 (&endp, 2 + inchars - cnt, - 0x80); - - if (ch == UNKNOWN_10646_CHAR) - ch = L'\0'; - if (ch != L'\0') - cnt += 2; - } - else - { - /* This is code set 1: CNS 11643, plane 1. */ - const char *endp = &inbuf[cnt - 1]; - - ch = cns11643l1_to_ucs4 (&endp, 2 + inchars - cnt, - 0x80); - - if (ch == UNKNOWN_10646_CHAR) - ch = L'\0'; - if (ch != L'\0') - ++cnt; - } - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - wchar_t ch = *((wchar_t *) (inbuf + cnt)); - - if (ch <= L'\x7f') - /* It's plain ASCII. */ - outbuf[outchars] = ch; - else - { - /* Try the JIS character sets. */ - size_t found; - - found = ucs4_to_cns11643l1 (ch, &outbuf[outchars], - (data->outbufsize - - outchars)); - if (found == 0) - { - /* We ran out of space. */ - extra = 2; - break; - } - else if (found != UNKNOWN_10646_CHAR) - { - /* It's a CNS 11643, plane 1 character, adjust it - for EUC-TW. */ - outbuf[outchars++] += 0x80; - outbuf[outchars] += 0x80; - } - else - { - /* No CNS 11643, plane 1 character. */ - outbuf[outchars] = '\x8e'; - - found = ucs4_to_cns11643 (ch, &outbuf[outchars + 1], - (data->outbufsize - - outchars - 1)); - if (found > 0) - { - /* It's a CNS 11643 character, adjust it for - EUC-TW. */ - outbuf[++outchars] += 0xa0; - outbuf[++outchars] += 0x80; - outbuf[outchars] += 0x80; - } - else if (found == 0) - { - /* We ran out of space. */ - extra = 4; - break; - } - else - /* Illegal character. */ - break; - } - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_euctw_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "EUC-TW" +#define FROM_LOOP from_euc_tw +#define TO_LOOP to_euc_tw +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 4 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from EUC-TW to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch <= 0x7f) \ + /* Plain ASCII. */ \ + ++inptr; \ + else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two or more byte character. First test whether the next \ + character is also available. */ \ + uint32_t ch2; \ + \ + if (NEED_LENGTH_TEST && inptr + (ch == 0x8e ? 3 : 1) >= inend) \ + { \ + /* The second character is not available. Store the \ + intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = *inptr; \ + \ + /* All second bytes of a multibyte character must be >= 0xa1. */ \ + if (ch2 < 0xa1 || ch2 == 0xff) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + if (ch == 0x8e) \ + { \ + /* This is code set 2: CNS 11643, planes 1 to 16. */ \ + const char *endp = inptr + 1; \ + \ + ch = cns11643_to_ucs4 (&endp, \ + NEED_LENGTH_TEST ? inend - inptr - 1 : 3, \ + 0x80); \ + /* Please note that we need not test for the missing input \ + characters here anymore. */ \ + if (ch == UNKNOWN_10646_CHAR) \ + { \ + /* Illegal input. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 4; \ + } \ + else \ + { \ + /* This is code set 1: CNS 11643, plane 1. */ \ + const char *endp = inptr; \ + \ + ch = cns11643l1_to_ucs4 (&endp, \ + NEED_LENGTH_TEST ? inend - inptr : 2, \ + 0x80); \ + /* Please note that we need not test for the missing input \ + characters here anymore. */ \ + if (ch == UNKNOWN_10646_CHAR) \ + { \ + /* Illegal input. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + \ + if (ch <= 0x7f) \ + /* It's plain ASCII. */ \ + *outptr++ = ch; \ + else \ + { \ + /* Try the JIS character sets. */ \ + size_t found; \ + \ + found = ucs4_to_cns11643l1 (ch, outptr, \ + NEED_LENGTH_TEST ? outend - outptr : 2); \ + if (NEED_LENGTH_TEST && found == 0) \ + { \ + /* We ran out of space. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + if (found != UNKNOWN_10646_CHAR) \ + { \ + /* It's a CNS 11643, plane 1 character, adjust it for EUC-TW. */ \ + *outptr++ += 0x80; \ + *outptr++ += 0x80; \ + } \ + else \ + { \ + /* No CNS 11643, plane 1 character. */ \ + \ + found = ucs4_to_cns11643 (ch, outptr + 1, \ + (NEED_LENGTH_TEST \ + ? outend - outptr - 1 : 3)); \ + if (NEED_LENGTH_TEST && found == 0) \ + { \ + /* We ran out of space. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + if (found == UNKNOWN_10646_CHAR) \ + { \ + /* No legal input. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + /* It's a CNS 11643 character, adjust it for EUC-TW. */ \ + *outptr++ = '\x8e'; \ + *outptr++ += 0xa0; \ + *outptr++ += 0x80; \ + *outptr++ += 0x80; \ + } \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/gb2312.c b/iconvdata/gb2312.c index 89d716196f..9cde1c8fe7 100644 --- a/iconvdata/gb2312.c +++ b/iconvdata/gb2312.c @@ -40,7 +40,7 @@ printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const uint16_t gb2312_to_ucs[] = +const uint16_t __gb2312_to_ucs[] = { [0x0000] = 0x3000, [0x0001] = 0x3001, [0x0002] = 0x3002, [0x0003] = 0x30fb, [0x0004] = 0x02c9, [0x0005] = 0x02c7, [0x0006] = 0x00a8, [0x0007] = 0x3003, @@ -1907,7 +1907,7 @@ const uint16_t gb2312_to_ucs[] = }; -const char gb2312_from_ucs4_tab1[][2] = +const char __gb2312_from_ucs4_tab1[][2] = { [0x00] = "\x21\x68", [0x03] = "\x21\x6c", [0x04] = "\x21\x27", [0x0c] = "\x21\x63", [0x0d] = "\x21\x40", [0x33] = "\x21\x41", @@ -1939,7 +1939,7 @@ const char gb2312_from_ucs4_tab1[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab2[][2] = +const char __gb2312_from_ucs4_tab2[][2] = { [0x0000] = "\x26\x21", [0x0001] = "\x26\x22", [0x0002] = "\x26\x23", [0x0003] = "\x26\x24", [0x0004] = "\x26\x25", [0x0005] = "\x26\x26", @@ -1980,7 +1980,7 @@ const char gb2312_from_ucs4_tab2[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab3[][2] = +const char __gb2312_from_ucs4_tab3[][2] = { [0x0000] = "\x27\x27", [0x000f] = "\x27\x21", [0x0010] = "\x27\x22", [0x0011] = "\x27\x23", [0x0012] = "\x27\x24", [0x0013] = "\x27\x25", @@ -2027,7 +2027,7 @@ const char gb2312_from_ucs4_tab3[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab4[][2] = +const char __gb2312_from_ucs4_tab4[][2] = { [0x0000] = "\x21\x2a", [0x0003] = "\x21\x2e", [0x0004] = "\x21\x2f", [0x0007] = "\x21\x30", [0x0008] = "\x21\x31", [0x0011] = "\x21\x2d", @@ -2059,7 +2059,7 @@ const char gb2312_from_ucs4_tab4[][2] = But we have a problem here since U+2225 maps to either 0x212C or 0x214E. We simply choose the first solution here. */ -const char gb2312_from_ucs4_tab5[][2] = +const char __gb2312_from_ucs4_tab5[][2] = { [0x0000] = "\x21\x66", [0x0013] = "\x21\x6d", [0x005d] = "\x22\x71", [0x005e] = "\x22\x72", [0x005f] = "\x22\x73", [0x0060] = "\x22\x74", @@ -2100,7 +2100,7 @@ const char gb2312_from_ucs4_tab5[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab6[][2] = +const char __gb2312_from_ucs4_tab6[][2] = { [0x0000] = "\x22\x59", [0x0001] = "\x22\x5a", [0x0002] = "\x22\x5b", [0x0003] = "\x22\x5c", [0x0004] = "\x22\x5d", [0x0005] = "\x22\x5e", @@ -2142,7 +2142,7 @@ const char gb2312_from_ucs4_tab6[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab7[][2] = +const char __gb2312_from_ucs4_tab7[][2] = { [0x0000] = "\x21\x21", [0x0001] = "\x21\x22", [0x0002] = "\x21\x23", [0x0003] = "\x21\x28", [0x0005] = "\x21\x29", [0x0008] = "\x21\x34", @@ -2243,7 +2243,7 @@ const char gb2312_from_ucs4_tab7[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab8[][2] = +const char __gb2312_from_ucs4_tab8[][2] = { [0x0000] = "\x52\x3b", [0x0001] = "\x36\x21", [0x0003] = "\x46\x5f", [0x0007] = "\x4d\x72", [0x0008] = "\x55\x49", [0x0009] = "\x48\x7d", @@ -4523,7 +4523,7 @@ const char gb2312_from_ucs4_tab8[][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char gb2312_from_ucs4_tab9[][2] = +const char __gb2312_from_ucs4_tab9[][2] = { [0x0000] = "\x23\x21", [0x0001] = "\x23\x22", [0x0002] = "\x23\x23", [0x0003] = "\x21\x67", [0x0004] = "\x23\x25", [0x0005] = "\x23\x26", diff --git a/iconvdata/gb2312.h b/iconvdata/gb2312.h index 922fcc8f77..df87950436 100644 --- a/iconvdata/gb2312.h +++ b/iconvdata/gb2312.h @@ -25,7 +25,7 @@ #include <stdint.h> /* Conversion table. */ -extern const uint16_t gb2312_to_ucs[]; +extern const uint16_t __gb2312_to_ucs[]; static inline wchar_t @@ -51,127 +51,166 @@ gb2312_to_ucs4 (const char **s, size_t avail, unsigned char offset) (*s) += 2; - return gb2312_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR); + return __gb2312_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR); } -extern const char gb2312_from_ucs4_tab1[][2]; -extern const char gb2312_from_ucs4_tab2[][2]; -extern const char gb2312_from_ucs4_tab3[][2]; -extern const char gb2312_from_ucs4_tab4[][2]; -extern const char gb2312_from_ucs4_tab5[][2]; -extern const char gb2312_from_ucs4_tab6[][2]; -extern const char gb2312_from_ucs4_tab7[][2]; -extern const char gb2312_from_ucs4_tab8[][2]; -extern const char gb2312_from_ucs4_tab9[][2]; +extern const char __gb2312_from_ucs4_tab1[][2]; +extern const char __gb2312_from_ucs4_tab2[][2]; +extern const char __gb2312_from_ucs4_tab3[][2]; +extern const char __gb2312_from_ucs4_tab4[][2]; +extern const char __gb2312_from_ucs4_tab5[][2]; +extern const char __gb2312_from_ucs4_tab6[][2]; +extern const char __gb2312_from_ucs4_tab7[][2]; +extern const char __gb2312_from_ucs4_tab8[][2]; +extern const char __gb2312_from_ucs4_tab9[][2]; static inline size_t ucs4_to_gb2312 (wchar_t wch, char *s, size_t avail) { unsigned int ch = (unsigned int) wch; char buf[2]; - const char *cp = NULL; + const char *cp = buf; - if (ch < 0xa4) - return UNKNOWN_10646_CHAR; - else if (ch < 0x101) - cp = gb2312_from_ucs4_tab1[ch - 0xa4]; - else if (ch == 0x113) - cp = "\x28\x25"; - else if (ch == 0x11b) - cp = "\x28\x27"; - else if (ch == 0x12b) - cp = "\x28\x29"; - else if (ch == 0x14d) - cp = "\x28\x2d"; - else if (ch == 0x16b) - cp = "\x28\x31"; - else if (ch == 0x1ce) - cp = "\x28\x23"; - else if (ch == 0x1d0) - cp = "\x28\x2b"; - else if (ch == 0x1d2) - cp = "\x28\x2f"; - else if (ch == 0x1d4) - cp = "\x28\x33"; - else if (ch == 0x1d6) - cp = "\x28\x35"; - else if (ch == 0x1d8) - cp = "\x28\x36"; - else if (ch == 0x1da) - cp = "\x28\x37"; - else if (ch == 0x1dc) - cp = "\x28\x38"; - else if (ch == 0x2c7) - cp = "\x21\x26"; - else if (ch == 0x2c9) - cp = "\x21\x25"; - else if (ch >= 0x391 && ch <= 0x3c9) - cp = gb2312_from_ucs4_tab2[ch - 0x391]; - else if (ch >= 0x401 && ch <= 0x451) - cp = gb2312_from_ucs4_tab3[ch - 0x401]; - else if (ch >= 0x2015 && ch <= 0x203b) - cp = gb2312_from_ucs4_tab4[ch - 0x2015]; - else if (ch >= 0x2103 && ch <= 0x22a5) - cp = gb2312_from_ucs4_tab5[ch - 0x2103]; - else if (ch == 0x2313) - cp = "\x21\x50"; - else if (ch >= 0x2460 && ch <= 0x249b) - cp = gb2312_from_ucs4_tab6[ch - 0x2460]; - else if (ch >= 0x2500 && ch <= 0x254b) + switch (ch) { + case 0xa4 ... 0x100: + cp = __gb2312_from_ucs4_tab1[ch - 0xa4]; + break; + case 0x113: + cp = "\x28\x25"; + break; + case 0x11b: + cp = "\x28\x27"; + break; + case 0x12b: + cp = "\x28\x29"; + break; + case 0x14d: + cp = "\x28\x2d"; + break; + case 0x16b: + cp = "\x28\x31"; + break; + case 0x1ce: + cp = "\x28\x23"; + break; + case 0x1d0: + cp = "\x28\x2b"; + break; + case 0x1d2: + cp = "\x28\x2f"; + break; + case 0x1d4: + cp = "\x28\x33"; + break; + case 0x1d6: + cp = "\x28\x35"; + break; + case 0x1d8: + cp = "\x28\x36"; + break; + case 0x1da: + cp = "\x28\x37"; + break; + case 0x1dc: + cp = "\x28\x38"; + break; + case 0x2c7: + cp = "\x21\x26"; + break; + case 0x2c9: + cp = "\x21\x25"; + break; + case 0x391 ... 0x3c9: + cp = __gb2312_from_ucs4_tab2[ch - 0x391]; + break; + case 0x401 ... 0x451: + cp = __gb2312_from_ucs4_tab3[ch - 0x401]; + break; + case 0x2015 ... 0x203b: + cp = __gb2312_from_ucs4_tab4[ch - 0x2015]; + break; + case 0x2103 ... 0x22a5: + cp = __gb2312_from_ucs4_tab5[ch - 0x2103]; + break; + case 0x2313: + cp = "\x21\x50"; + break; + case 0x2460 ... 0x249b: + cp = __gb2312_from_ucs4_tab6[ch - 0x2460]; + break; + case 0x2500 ... 0x254b: buf[0] = '\x29'; buf[1] = '\x24' + (ch & 256); - cp = buf; - } - else if (ch == 0x25a0) - cp = "\x21\x76"; - else if (ch == 0x25a1) - cp = "\x21\x75"; - else if (ch == 0x25b2) - cp = "\x21\x78"; - else if (ch == 0x25b3) - cp = "\x21\x77"; - else if (ch == 0x25c6) - cp = "\x21\x74"; - else if (ch == 0x25c7) - cp = "\x21\x73"; - else if (ch == 0x25cb) - cp = "\x21\x70"; - else if (ch == 0x25ce) - cp = "\x21\x72"; - else if (ch == 0x25cf) - cp = "\x21\x71"; - else if (ch == 0x2605) - cp = "\x21\x6f"; - else if (ch == 0x2606) - cp = "\x21\x6e"; - else if (ch == 0x2640) - cp = "\x21\x62"; - else if (ch == 0x2642) - cp = "\x21\x61"; - else if (ch >= 0x3000 && ch <= 0x3129) - cp = gb2312_from_ucs4_tab7[ch - 0x3000]; - else if (ch >= 0x3220 && ch <= 0x3229) - { + break; + case 0x25a0: + cp = "\x21\x76"; + break; + case 0x25a1: + cp = "\x21\x75"; + break; + case 0x25b2: + cp = "\x21\x78"; + break; + case 0x25b3: + cp = "\x21\x77"; + break; + case 0x25c6: + cp = "\x21\x74"; + break; + case 0x25c7: + cp = "\x21\x73"; + break; + case 0x25cb: + cp = "\x21\x70"; + break; + case 0x25ce: + cp = "\x21\x72"; + break; + case 0x25cf: + cp = "\x21\x71"; + break; + case 0x2605: + cp = "\x21\x6f"; + break; + case 0x2606: + cp = "\x21\x6e"; + break; + case 0x2640: + cp = "\x21\x62"; + break; + case 0x2642: + cp = "\x21\x61"; + break; + case 0x3000 ... 0x3129: + cp = __gb2312_from_ucs4_tab7[ch - 0x3000]; + break; + case 0x3220 ... 0x3229: buf[0] = '\x22'; buf[1] = '\x65' + (ch - 0x3220); - cp = buf; + break; + case 0x4e00 ... 0x9fa0: + cp = __gb2312_from_ucs4_tab8[ch - 0x4e00]; + break; + case 0xff01 ... 0xff5e: + cp = __gb2312_from_ucs4_tab9[ch - 0xff01]; + break; + case 0xffe0: + cp = "\x21\x69"; + break; + case 0xffe1: + cp = "\x21\x6a"; + break; + case 0xffe3: + cp = "\x23\x7e"; + break; + case 0xffe5: + cp = "\x23\x24"; + break; + default: + return UNKNOWN_10646_CHAR; } - else if (ch >= 0x4e00 && ch <= 0x9fa0) - cp = gb2312_from_ucs4_tab8[ch - 0x4e00]; - else if (ch >= 0xff01 && ch <= 0xff5e) - cp = gb2312_from_ucs4_tab9[ch - 0xff01]; - else if (ch == 0xffe0) - cp = "\x21\x69"; - else if (ch == 0xffe1) - cp = "\x21\x6a"; - else if (ch == 0xffe3) - cp = "\x23\x7e"; - else if (ch == 0xffe5) - cp = "\x23\x24"; - else - return UNKNOWN_10646_CHAR; if (cp[1] != '\0' && avail < 2) return 0; diff --git a/iconvdata/hp-roman8.c b/iconvdata/hp-roman8.c index db36ceab9d..62e29ea463 100644 --- a/iconvdata/hp-roman8.c +++ b/iconvdata/hp-roman8.c @@ -1,5 +1,5 @@ /* Conversion from and to HP-ROMAN8. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,12 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> + +/* Get the conversion table. */ #include <hp-roman8.h> -#define NAME "HP-ROMAN8" + +#define CHARSET_NAME "HP-ROMAN8" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso646.c b/iconvdata/iso646.c index 53ca76cb14..3c40c8fd0c 100644 --- a/iconvdata/iso646.c +++ b/iconvdata/iso646.c @@ -292,19 +292,17 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, /* Correct the output buffer. */ if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } + memmove (data->outbuf, + &data->outbuf[data->outbufavail - newavail], + newavail); + data->outbufavail = newavail; } } while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); } if (written != NULL && data->is_last) - *written = do_write; + *written += do_write; return result; } diff --git a/iconvdata/iso6937.c b/iconvdata/iso6937.c index 21e3ab4898..b121ffa77a 100644 --- a/iconvdata/iso6937.c +++ b/iconvdata/iso6937.c @@ -18,11 +18,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> -#include <string.h> +#include <stdint.h> /* Data taken from the WG15 tables. */ -static const wchar_t to_ucs4[256] = +static const uint32_t to_ucs4[256] = { /* 0x00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, /* 0x08 */ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, @@ -60,7 +59,7 @@ static const wchar_t to_ucs4[256] = /* The outer array range runs from 0xc1 to 0xcf, the inner range from 0x20 to 0x7f. */ -static const wchar_t to_ucs4_comb[15][96] = +static const uint32_t to_ucs4_comb[15][96] = { /* 0xc1 */ { @@ -371,290 +370,179 @@ static const char from_ucs4[][2] = */ }; -/* Direction of the transformation. */ -static int to_iso6937_object; -static int from_iso6937_object; +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "ISO_6937" +#define FROM_LOOP from_iso6937 +#define TO_LOOP to_iso6937 +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from ISO 6937 to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch >= 0xc1 && ch <= 0xcf) \ + { \ + /* Composed character. First test whether the next character \ + is also available. */ \ + int ch2; \ + \ + if (inptr + 1 >= inend) \ + { \ + /* The second character is not available. Store the \ + intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + \ + if (ch2 < 0x20 || ch2 >= 0x80) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20]; \ + \ + if (ch == 0) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + else \ + { \ + ch = to_ucs4[ch]; \ + \ + if (ch == 0 && *inptr != '\0') \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + ++inptr; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + char tmp[2]; \ + uint32_t ch = *((uint32_t *) inptr); \ + const char *cp; \ + \ + if (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0])) \ + { \ + int fail = 0; \ + switch (ch) \ + { \ + case 0x2c7: \ + cp = "\xcf\x20"; \ + break; \ + case 0x2d8 ... 0x2dd: \ + { \ + static const char map[5] = "\xc6\xc7\xca\xce\xcd"; \ + \ + tmp[0] = map[ch - 0x2d8]; \ + tmp[1] = ' '; \ + cp = tmp; \ + } \ + break; \ + case 0x2014: \ + cp = "\xd0"; \ + break; \ + case 0x2018: \ + cp = "\xa9"; \ + break; \ + case 0x2019: \ + cp = "\xb9"; \ + break; \ + case 0x201c: \ + cp = "\xaa"; \ + break; \ + case 0x201d: \ + cp = "\xba"; \ + break; \ + case 0x2122: \ + cp = "\xd4"; \ + break; \ + case 0x2126: \ + cp = "\xe0"; \ + break; \ + case 0x215b ... 0x215e: \ + tmp[0] = 0xdc + (ch - 0x215b); \ + tmp[1] = '\0'; \ + cp = tmp; \ + break; \ + case 0x2190 ... 0x2193: \ + tmp[0] = 0xac + (ch - 0x2190); \ + tmp[1] = '\0'; \ + cp = tmp; \ + break; \ + case 0x266a: \ + cp = "\xd5"; \ + break; \ + default: \ + cp = NULL; \ + fail = 1; \ + } \ + \ + if (fail) \ + { \ + /* Illegal characters. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + else if (from_ucs4[ch][0] == '\0' && ch != 0) \ + { \ + /* Illegal characters. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + cp = from_ucs4[ch]; \ + \ + *outptr++ = cp[0]; \ + /* Now test for a possible second byte and write this if possible. */ \ + if (cp[1] != '\0') \ + { \ + if (NEED_LENGTH_TEST && outptr >= outend) \ + { \ + /* The result does not fit into the buffer. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + *outptr++ = cp[1]; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "ISO_6937") != NULL) - step->data = &from_iso6937_object; - else if (strcasestr (step->to_name, "ISO_6937") != NULL) - step->data = &to_iso6937_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothign to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_iso6937_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = inbuf[cnt]; - wchar_t ch; - - if (inchar >= '\xc1' && inchar <= '\xcf') - { - /* Composed character. First test whether the next - character is also available. */ - int inchar2; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = inbuf[++cnt]; - - if (inchar2 < '\x20' || inchar2 >= '\x80') - /* This is illegal. */ - ch = L'\0'; - else - ch = to_ucs4_comb[inchar - 0xc1][inchar2 - 0x20]; - - if (ch == L'\0') - /* Undo the increment for illegal characters. */ - --cnt; - } - else - ch = to_ucs4[inchar]; - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - char tmp[2]; - int ch = *((wchar_t *) (inbuf + cnt)); - const char *cp; - - if (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0])) - { - int fail = 0; - switch (ch) - { - case 0x2c7: - cp = "\xcf\x20"; - break; - case 0x2d8 ... 0x2dd: - { - static const char map[5] = "\xc6\xc7\xca\xce\xcd"; - - tmp[0] = map[ch - 0x2d8]; - tmp[1] = ' '; - cp = tmp; - } - break; - case 0x2014: - cp = "\xd0"; - break; - case 0x2018: - cp = "\xa9"; - break; - case 0x2019: - cp = "\xb9"; - break; - case 0x201c: - cp = "\xaa"; - break; - case 0x201d: - cp = "\xba"; - break; - case 0x2122: - cp = "\xd4"; - break; - case 0x2126: - cp = "\xe0"; - break; - case 0x215b ... 0x215e: - tmp[0] = 0xdc + (ch - 0x215b); - tmp[1] = '\0'; - cp = tmp; - break; - case 0x2190 ... 0x2193: - tmp[0] = 0xac + (ch - 0x2190); - tmp[1] = '\0'; - cp = tmp; - break; - case 0x266a: - cp = "\xd5"; - break; - default: - cp = NULL; - fail = 1; - } - - if (fail) - /* Illegal characters. */ - break; - } - else if (ch < 0 || (from_ucs4[ch][0] == '\0' && ch != 0)) - break; - else - cp = from_ucs4[ch]; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_iso6937_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - return result; -} +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/iso8859-1.c b/iconvdata/iso8859-1.c index b9484a06b7..3e50b79f17 100644 --- a/iconvdata/iso8859-1.c +++ b/iconvdata/iso8859-1.c @@ -18,179 +18,44 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> -#include <string.h> - -/* Direction of the transformation. */ -static int to_iso88591_object; -static int from_iso88591_object; - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "ISO-8859-1") != NULL) - step->data = &from_iso88591_object; - else if (strcasestr (step->to_name, "ISO-8859-1") != NULL) - step->data = &to_iso88591_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_iso88591_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - *((wchar_t *) (outbuf + outwchars)) = - (unsigned char) inbuf[cnt]; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - if (*((wchar_t *) (inbuf + cnt)) >= L'\0' - && *((wchar_t *) (inbuf + cnt)) <= L'\377') - outbuf[outchars] = *((wchar_t *) (inbuf + cnt)); - else - /* Here is where the transliteration would enter the - scene. */ - break; - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_iso88591_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +#include <stdint.h> + +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "ISO-8859-1" +#define FROM_LOOP from_iso8859_1 +#define TO_LOOP to_iso8859_1 +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MIN_NEEDED_TO 4 + +/* First define the conversion function from ISO 8859-1 to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + *((uint32_t *) outptr)++ = *inptr++; +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + if (ch > 0xff) \ + { \ + /* We have an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + *outptr++ = (unsigned char) ch; \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/iso8859-10.c b/iconvdata/iso8859-10.c index eb54e49342..acce3257e3 100644 --- a/iconvdata/iso8859-10.c +++ b/iconvdata/iso8859-10.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-10. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-10.h> -#define NAME "ISO-8859-10" + +#define CHARSET_NAME "ISO-8859-10" +#define HAS_HOLES 0 /* All 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-2.c b/iconvdata/iso8859-2.c index fa07b752c6..8a5e62418f 100644 --- a/iconvdata/iso8859-2.c +++ b/iconvdata/iso8859-2.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-2. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-2.h> -#define NAME "ISO-8859-2" + +#define CHARSET_NAME "ISO-8859-2" +#define HAS_HOLES 0 /* All 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-3.c b/iconvdata/iso8859-3.c index c31d388ca2..10e52e429f 100644 --- a/iconvdata/iso8859-3.c +++ b/iconvdata/iso8859-3.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-3. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-3.h> -#define NAME "ISO-8859-3" + +#define CHARSET_NAME "ISO-8859-3" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-4.c b/iconvdata/iso8859-4.c index 7ae98473ca..01cdbf0b98 100644 --- a/iconvdata/iso8859-4.c +++ b/iconvdata/iso8859-4.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-4. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-4.h> -#define NAME "ISO-8859-4" + +#define CHARSET_NAME "ISO-8859-4" +#define HAS_HOLES 0 /* All 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-5.c b/iconvdata/iso8859-5.c index b4791f1bf5..edf0f47b5c 100644 --- a/iconvdata/iso8859-5.c +++ b/iconvdata/iso8859-5.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-5. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-5.h> -#define NAME "ISO-8859-5" + +#define CHARSET_NAME "ISO-8859-5" +#define HAS_HOLES 0 /* All 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-6.c b/iconvdata/iso8859-6.c index 1e88ec9d22..59ce3f2cc1 100644 --- a/iconvdata/iso8859-6.c +++ b/iconvdata/iso8859-6.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-6. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-6.h> -#define NAME "ISO-8859-6" + +#define CHARSET_NAME "ISO-8859-6" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-7.c b/iconvdata/iso8859-7.c index 63220bb822..d75e93e204 100644 --- a/iconvdata/iso8859-7.c +++ b/iconvdata/iso8859-7.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-7. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-7.h> -#define NAME "ISO-8859-7" + +#define CHARSET_NAME "ISO-8859-7" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-8.c b/iconvdata/iso8859-8.c index 2246ae4e52..1612f148f4 100644 --- a/iconvdata/iso8859-8.c +++ b/iconvdata/iso8859-8.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-8. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-8.h> -#define NAME "ISO-8859-8" + +#define CHARSET_NAME "ISO-8859-8" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/iso8859-9.c b/iconvdata/iso8859-9.c index 5260362f0c..063f189aba 100644 --- a/iconvdata/iso8859-9.c +++ b/iconvdata/iso8859-9.c @@ -1,5 +1,5 @@ /* Conversion from and to ISO 8859-9. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <iso8859-9.h> -#define NAME "ISO-8859-9" + +#define CHARSET_NAME "ISO-8859-9" +#define HAS_HOLES 0 /* All 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/jis0201.c b/iconvdata/jis0201.c index e8e04e171b..65321e4cd7 100644 --- a/iconvdata/jis0201.c +++ b/iconvdata/jis0201.c @@ -1,5 +1,5 @@ /* Mapping tables for JIS0201 handling. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,10 +18,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> -const wchar_t jisx0201_to_ucs4[256] = +const uint32_t __jisx0201_to_ucs4[256] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, diff --git a/iconvdata/jis0201.h b/iconvdata/jis0201.h index 8f920f9ec8..1514c88d73 100644 --- a/iconvdata/jis0201.h +++ b/iconvdata/jis0201.h @@ -22,13 +22,13 @@ #define _JIS0201_H 1 /* Conversion table. */ -extern const wchar_t jis0201_to_ucs4[]; +extern const uint32_t __jis0201_to_ucs4[]; -static inline wchar_t +static inline uint32_t jisx0201_to_ucs4 (char ch) { - wchar_t val = jis0201_to_ucs4[(unsigned char) ch]; + uint32_t val = __jis0201_to_ucs4[(unsigned char) ch]; if (val == 0 && ch != '\0') val = UNKNOWN_10646_CHAR; @@ -38,7 +38,7 @@ jisx0201_to_ucs4 (char ch) static inline size_t -ucs4_to_jisx0201 (wchar_t wch, char *s) +ucs4_to_jisx0201 (uint32_t wch, char *s) { char ch; diff --git a/iconvdata/jis0208.c b/iconvdata/jis0208.c index 8db4085a9c..964f73dd26 100644 --- a/iconvdata/jis0208.c +++ b/iconvdata/jis0208.c @@ -1,5 +1,5 @@ /* Mapping tables for JIS0208 handling. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> #include "jis0208.h" @@ -58,7 +58,7 @@ printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const uint16_t jis0208_to_ucs[0x1e80] = +const uint16_t __jis0208_to_ucs[0x1e80] = { [0x0000] = 0x3000, [0x0001] = 0x3001, [0x0002] = 0x3002, [0x0003] = 0xff0c, [0x0004] = 0xff0e, [0x0005] = 0x30fb, [0x0006] = 0xff1a, [0x0007] = 0xff1b, @@ -1783,7 +1783,7 @@ const uint16_t jis0208_to_ucs[0x1e80] = }; -const char jisx0208_from_ucs4_lat1[256][2] = +const char __jisx0208_from_ucs4_lat1[256][2] = { [0x005C] = "\x21\x40", [0x00A2] = "\x21\x71", [0x00A3] = "\x21\x72", [0x00A7] = "\x21\x78", [0x00A8] = "\x21\x2f", [0x00AC] = "\x22\x4c", @@ -1814,7 +1814,7 @@ const char jisx0208_from_ucs4_lat1[256][2] = printf ("\n"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char jisx0208_from_ucs4_greek[0xc1][2] = +const char __jisx0208_from_ucs4_greek[0xc1][2] = { [0x00] = "\x26\x21", [0x01] = "\x26\x22", [0x02] = "\x26\x23", [0x03] = "\x26\x24", [0x04] = "\x26\x25", [0x05] = "\x26\x26", @@ -1887,7 +1887,7 @@ const char jisx0208_from_ucs4_greek[0xc1][2] = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const struct jisx0208_ucs_idx jisx0208_from_ucs_idx[] = +const struct jisx0208_ucs_idx __jisx0208_from_ucs_idx[] = { { start: 0x2010, end: 0x2026, idx: 0 }, { start: 0x2030, end: 0x2033, idx: 23 }, @@ -2596,7 +2596,7 @@ const struct jisx0208_ucs_idx jisx0208_from_ucs_idx[] = { start: 0x9f9c, end: 0x9fa0, idx: 14109 }, { start: 0xff01, end: 0xff5d, idx: 14114 }, { start: 0xffe3, end: 0xffe5, idx: 14207 }, - { start: 0 } + { start: 0xffff, end: 0xffff, idx: 0 } }; @@ -2637,7 +2637,7 @@ const struct jisx0208_ucs_idx jisx0208_from_ucs_idx[] = } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char jisx0208_from_ucs_tab[14210][2] = +const char __jisx0208_from_ucs_tab[14210][2] = { "\x20\x10", "\x00\x00", "\x00\x00", "\x00\x00", "\x00\x00", "\x20\x15", "\x20\x16", "\x00\x00", "\x20\x18", "\x20\x19", "\x00\x00", "\x00\x00", diff --git a/iconvdata/jis0208.h b/iconvdata/jis0208.h index 94d27642c6..a83ee3bbda 100644 --- a/iconvdata/jis0208.h +++ b/iconvdata/jis0208.h @@ -25,12 +25,12 @@ #include <stdint.h> /* Conversion table. */ -extern const uint16_t jis0208_to_ucs[]; +extern const uint16_t __jis0208_to_ucs[]; -extern const char jisx0208_from_ucs4_lat1[256][2]; -extern const char jisx0208_from_ucs4_greek[0xc1][2]; -extern const struct jisx0208_ucs_idx jisx0208_from_ucs_idx[]; -extern const char jisx0208_from_ucs_tab[][2]; +extern const char __jisx0208_from_ucs4_lat1[256][2]; +extern const char __jisx0208_from_ucs4_greek[0xc1][2]; +extern const struct jisx0208_ucs_idx __jisx0208_from_ucs_idx[]; +extern const char __jisx0208_from_ucs_tab[][2]; /* Struct for table with indeces in UCS mapping table. */ @@ -42,8 +42,8 @@ struct jisx0208_ucs_idx }; -static inline wchar_t -jisx0208_to_ucs4 (const char **s, size_t avail, unsigned char offset) +static inline uint32_t +jisx0208_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset) { unsigned char ch = *(*s); unsigned char ch2; @@ -65,34 +65,38 @@ jisx0208_to_ucs4 (const char **s, size_t avail, unsigned char offset) (*s) += 2; - return jis0208_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR); + return __jis0208_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR); } static inline size_t -ucs4_to_jisx0208 (wchar_t wch, char *s, size_t avail) +ucs4_to_jisx0208 (uint32_t wch, char *s, size_t avail) { unsigned int ch = (unsigned int) wch; - const char *cp = NULL; + const char *cp; if (avail < 2) return 0; if (ch < 0x100) - cp = jisx0208_from_ucs4_lat1[ch]; + cp = __jisx0208_from_ucs4_lat1[ch]; else if (ch >= 0x391 && ch <= 0x451) - cp = jisx0208_from_ucs4_greek[ch]; + cp = __jisx0208_from_ucs4_greek[ch]; else { - const struct jisx0208_ucs_idx *rp = jisx0208_from_ucs_idx; + const struct jisx0208_ucs_idx *rp = __jisx0208_from_ucs_idx; + if (ch >= 0xffff) + return UNKNOWN_10646_CHAR; while (ch > rp->end) ++rp; if (ch >= rp->start) - cp = jisx0208_from_ucs_tab[rp->idx + ch - rp->start]; + cp = __jisx0208_from_ucs_tab[rp->idx + ch - rp->start]; + else + return UNKNOWN_10646_CHAR; } - if (cp == NULL || cp[0] == '\0') + if (cp[0] == '\0') return UNKNOWN_10646_CHAR; s[0] = cp[0]; diff --git a/iconvdata/jis0212.c b/iconvdata/jis0212.c index 7484c5e84c..eca645f45a 100644 --- a/iconvdata/jis0212.c +++ b/iconvdata/jis0212.c @@ -19,7 +19,6 @@ Boston, MA 02111-1307, USA. */ #include <stdint.h> -#include <wchar.h> #include <jis0212.h> @@ -54,7 +53,7 @@ $first, $last, $idx); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const struct jisx0212_idx jisx0212_to_ucs_idx[] = +const struct jisx0212_idx __jisx0212_to_ucs_idx[] = { { start: 0x006c, end: 0x0076, idx: 0 }, { start: 0x007f, end: 0x0081, idx: 11 }, @@ -67,7 +66,7 @@ const struct jisx0212_idx jisx0212_to_ucs_idx[] = { start: 0x034e, end: 0x03a4, idx: 107 }, { start: 0x03ac, end: 0x0402, idx: 194 }, { start: 0x0582, end: 0x1c2a, idx: 281 }, - { start: 0 }, + { start: 0xffff, end: 0xffff, idx: 0 }, }; @@ -109,7 +108,7 @@ const struct jisx0212_idx jisx0212_to_ucs_idx[] = } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const uint16_t jisx0212_to_ucs[] = +const uint16_t __jisx0212_to_ucs[] = { 0x02d8, 0x02c7, 0x00b8, 0x02d9, 0x02dd, 0x00af, 0x02db, 0x02da, 0x007e, 0x0384, 0x0385, 0x00a1, 0x00a6, 0x00bf, 0x00ba, 0x00aa, @@ -905,7 +904,7 @@ const uint16_t jisx0212_to_ucs[] = $first, $last, $idx); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const struct jisx0212_idx jisx0212_from_ucs_idx[] = +const struct jisx0212_idx __jisx0212_from_ucs_idx[] = { { start: 0x007e, end: 0x007e, idx: 0 }, { start: 0x00a1, end: 0x00af, idx: 1 }, @@ -1654,7 +1653,7 @@ const struct jisx0212_idx jisx0212_from_ucs_idx[] = { start: 0x9f68, end: 0x9f7d, idx: 13393 }, { start: 0x9f8f, end: 0x9f97, idx: 13415 }, { start: 0x9f9e, end: 0x9fa5, idx: 13424 }, - { start: 0 } + { start: 0xffff, end: 0xffff, idx: 0 } }; @@ -1697,7 +1696,7 @@ const struct jisx0212_idx jisx0212_from_ucs_idx[] = } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -const char jisx0212_from_ucs[][2] = +const char __jisx0212_from_ucs[][2] = { "\x7e\x00", "\xa1\x00", "\x00\x00", "\x00\x00", "\xa4\x00", "\x00\x00", "\xa6\x00", "\x00\x00", "\x00\x00", "\xa9\x00", "\xaa\x00", "\x00\x00", diff --git a/iconvdata/jis0212.h b/iconvdata/jis0212.h index cf5d919109..4930437128 100644 --- a/iconvdata/jis0212.h +++ b/iconvdata/jis0212.h @@ -34,20 +34,20 @@ struct jisx0212_idx }; /* Conversion table. */ -extern const struct jisx0212_idx jisx0212_to_ucs_idx[]; -extern const uint16_t jisx0212_to_ucs[]; +extern const struct jisx0212_idx __jisx0212_to_ucs_idx[]; +extern const uint16_t __jisx0212_to_ucs[]; -extern const struct jisx0212_idx jisx0212_from_ucs_idx[]; -extern const char jisx0212_from_ucs[][2]; +extern const struct jisx0212_idx __jisx0212_from_ucs_idx[]; +extern const char __jisx0212_from_ucs[][2]; static inline wchar_t -jisx0212_to_ucs4 (const char **s, size_t avail, unsigned char offset) +jisx0212_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset) { - const struct jisx0212_idx *rp = jisx0212_to_ucs_idx; + const struct jisx0212_idx *rp = __jisx0212_to_ucs_idx; unsigned char ch = *(*s); unsigned char ch2; - wchar_t wch = L'\0'; + uint32_t wch = 0; int idx; if (ch < offset || (ch - offset) <= 0x6d || (ch - offset) > 0xea) @@ -62,10 +62,10 @@ jisx0212_to_ucs4 (const char **s, size_t avail, unsigned char offset) idx = (ch - 0x21 - offset) * 94 + (ch2 - 0x21 - offset); - while (idx < rp->start) + while (idx > rp->end) ++rp; - if (idx <= rp->end) - wch = jisx0212_to_ucs[rp->idx + idx - rp->start]; + if (idx >= rp->start) + wch = __jisx0212_to_ucs[rp->idx + idx - rp->start]; if (wch != L'\0') (*s) += 2; @@ -79,16 +79,20 @@ jisx0212_to_ucs4 (const char **s, size_t avail, unsigned char offset) static inline size_t ucs4_to_jisx0212 (wchar_t wch, char *s, size_t avail) { - const struct jisx0212_idx *rp = jisx0212_from_ucs_idx; + const struct jisx0212_idx *rp = __jisx0212_from_ucs_idx; unsigned int ch = (unsigned int) wch; - const char *cp = NULL; + const char *cp; + if (ch >= 0xffff) + return UNKNOWN_10646_CHAR; while (ch > rp->end) ++rp; if (ch >= rp->start) - cp = jisx0212_from_ucs[rp->idx + ch - rp->start]; + cp = __jisx0212_from_ucs[rp->idx + ch - rp->start]; + else + return UNKNOWN_10646_CHAR; - if (cp == NULL || cp[0] == '\0') + if (cp[0] == '\0') return UNKNOWN_10646_CHAR; s[0] = cp[0]; diff --git a/iconvdata/johab.c b/iconvdata/johab.c index c9912a71d0..6a582c0b70 100644 --- a/iconvdata/johab.c +++ b/iconvdata/johab.c @@ -1,7 +1,8 @@ /* Mapping tables for JOHAB handling. Copyright (C) 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Jungshik Shin <jshin@pantheon.yale.edu>, 1998. + Contributed by Jungshik Shin <jshin@pantheon.yale.edu> + and Ulrich Drepper <drepper@cygnus.com>, 1998. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -18,16 +19,9 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <string.h> -#include <wchar.h> #include <ksc5601.h> -/* Direction of the transformation. */ -static int to_johab_object; -static int from_johab_object; - /* The table for Bit pattern to Hangul Jamo 5 bits each are used to encode leading consonants(19 + 1 filler), medial vowels(21 + 1 filler) @@ -37,19 +31,19 @@ static int from_johab_object; 0 : Filler, -1: invalid, >= 1 : valid */ -const int init[32] = +static const int init[32] = { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -const int mid[32] = +static const int mid[32] = { -1, -1, 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, 12, 13, 14, 15, 16, 17, -1, -1, 18, 19, 20, 21, -1, -1 }; -const int final[32] = +static const int final[32] = { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1 @@ -63,14 +57,14 @@ const int final[32] = block [0x3131,0x314e] or Hangul Conjoining Jamo block, [0x1100,0x11ff] */ -const wchar_t init_to_ucs[19] = +static const uint32_t init_to_ucs[19] = { 0x3131, 0x3132, 0x3134, 0x3137, 0x3138, 0x3139, 0x3141, 0x3142, 0x3143, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e }; -const wchar_t final_to_ucs[27] = +static const uint32_t final_to_ucs[27] = { L'\0', L'\0', 0x3133, L'\0', 0x3135, 0x3136, L'\0', L'\0', 0x313a, 0x313b, 0x314c, 0x313d, 0x313e, 0x313f, @@ -88,7 +82,7 @@ const wchar_t final_to_ucs[27] = to get the same result arithmetically. */ -const int init_to_bit[19] = +static const int init_to_bit[19] = { 0x8800, 0x8c00, 0x9000, 0x9400, 0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, @@ -96,7 +90,7 @@ const int init_to_bit[19] = 0xd000 }; -const int mid_to_bit[21] = +static const int mid_to_bit[21] = { 0x0060, 0x0080, 0x00a0, 0x00c0, 0x00e0, 0x0140, 0x0160, 0x0180, 0x01a0, 0x01c0, 0x1e0, @@ -104,7 +98,7 @@ const int mid_to_bit[21] = 0x0340, 0x0360, 0x0380, 0x03a0 }; -const int final_to_bit[28] = +static const int final_to_bit[28] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d @@ -118,7 +112,7 @@ const int final_to_bit[28] = 2. Unicode 2.0 manual */ -const uint16_t jamo_from_ucs_table[51] = +static const uint16_t jamo_from_ucs_table[51] = { 0x8841, 0x8c41, 0x8444, @@ -137,21 +131,20 @@ const uint16_t jamo_from_ucs_table[51] = }; -static inline wchar_t -johab_sym_hanja_to_ucs (int idx, int c1, int c2) +static inline uint32_t +johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2) { if (idx <= 0xdefe) - return (wchar_t) ksc5601_sym_to_ucs[(c1 - 0xd9) * 188 + c2 - - (c2 > 0x90 ? 0x43 : 0x31)]; + return (uint32_t) __ksc5601_sym_to_ucs[(c1 - 0xd9) * 188 + c2 + - (c2 > 0x90 ? 0x43 : 0x31)]; else - return (wchar_t) ksc5601_hanja_to_ucs[(c1 - 0xe0) * 188 + c2 - - (c2 > 0x90 ? 0x43 : 0x31)]; + return (uint32_t) __ksc5601_hanja_to_ucs[(c1 - 0xe0) * 188 + c2 + - (c2 > 0x90 ? 0x43 : 0x31)]; } static uint16_t -johab_hanja_from_ucs (wchar_t ch) +johab_hanja_from_ucs (uint32_t ch) { - uint16_t idx; if (ucs4_to_ksc5601_hanja (ch, &idx)) { @@ -168,7 +161,7 @@ johab_hanja_from_ucs (wchar_t ch) } static uint16_t -johab_sym_from_ucs (wchar_t ch) +johab_sym_from_ucs (uint32_t ch) { uint16_t idx; if (ucs4_to_ksc5601_sym (ch, &idx)) @@ -186,9 +179,8 @@ johab_sym_from_ucs (wchar_t ch) } - static inline void -johab_from_ucs4 (wchar_t ch, unsigned char *cp) +johab_from_ucs4 (uint32_t ch, unsigned char *cp) { if (ch >= 0x7f) { @@ -215,315 +207,205 @@ johab_from_ucs4 (wchar_t ch, unsigned char *cp) else idx = johab_sym_from_ucs (ch); - *cp = (char) (idx / 256); - *(cp + 1) = (char) (idx & 0xff); + cp[0] = (unsigned char) (idx / 256); + cp[1] = (unsigned char) (idx & 0xff); } else { - *cp = (char) (0x7f & ch); - *(cp + 1) = (char) 0; + cp[0] = (unsigned char) ch; + cp[1] = 0; } - -} - - -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "JOHAB") != NULL) - step->data = &from_johab_object; - else if (strcasestr (step->to_name, "JOHAB") != NULL) - step->data = &to_johab_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ } -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t * written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_johab_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = (unsigned char) inbuf[cnt]; - wchar_t ch; - /* half-width Korean Currency WON sign - if (inchar == 0x5c) - ch = 0x20a9; - else if (inchar < 0x7f) - ch = (wchar_t) inchar; - */ - if (inchar < 0x7f) - ch = (wchar_t) inchar; - - /* Johab : 1. Hangul - 1st byte : 0x84-0xd3 - 2nd byte : 0x41-0x7e, 0x81-0xfe - 2. Hanja & Symbol : - 1st byte : 0xd8-0xde, 0xe0-0xf9 - 2nd byte : 0x31-0x7e, 0x91-0xfe - 0xd831-0xd87e and 0xd891-0xd8fe are user-defined area */ - - else if (inchar > 0xf9 || inchar == 0xdf - || (inchar > 0x7e && inchar < 0x84) - || (inchar > 0xd3 && inchar < 0xd9)) - /* These are illegal. */ - ch = L'\0'; - else - { - /* Two-byte character. First test whether the next - character is also available. */ - int inchar2; - int idx; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = (unsigned char) inbuf[++cnt]; - idx = inchar * 256 + inchar2; - if (inchar <= 0xd3) - { /* Hangul */ - int i, m, f; - i = init[(idx & 0x7c00) >> 10]; - m = mid[(idx & 0x03e0) >> 5]; - f = final[idx & 0x001f]; - if (i == -1 || m == -1 || f == -1) - /* This is illegal. */ - ch = L'\0'; - else if (i > 0 && m > 0) - ch = ((i - 1) * 21 + (m - 1)) * 28 + f + 0xac00; - else if (i > 0 && m == 0 & f == 0) - ch = init_to_ucs[i - 1]; - else if (i == 0 && m > 0 & f == 0) - ch = 0x314e + m; /* 0x314f + m - 1 */ - else if (i == 0 && m == 0 & f > 0) - ch = final_to_ucs[f - 1]; /* round trip?? */ - else - /* This is illegal. */ - ch = L'\0'; - } - else - { - if (inchar2 < 0x31 - || (inchar2 > 0x7e && inchar2 < 0x91) - || inchar2 == 0xff) - /* This is illegal. */ - ch = L'\0'; - else if (inchar == 0xda - && inchar2 > 0xa0 && inchar2 < 0xd4) - /* This is illegal. */ - /* Modern Hangul Jaso is defined elsewhere - in Johab */ - ch = L'\0'; - else - { - ch = johab_sym_hanja_to_ucs (idx, inchar, - inchar2); - /* if (idx <= 0xdefe) - ch = ksc5601_sym_to_ucs[(inchar - 0xd9) * 192 - + inchar2 - - (inchar2>0x90 ? 0x43 : 0x31)]; - - else - ch = ksc5601_hanja_to_ucs[(inchar - 0xe0) *192 - + inchar2 - - (inchar2>0x90 ? 0x43 : 0x31)]; - */ - } - } - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - wchar_t ch = *((wchar_t *) (inbuf + cnt)); - unsigned char cp[2]; - /* - if (ch >= (sizeof (from_ucs4_lat1) - / sizeof (from_ucs4_lat1[0]))) - { - if (ch >= 0x0391 && ch <= 0x0451) - cp = from_ucs4_greek[ch - 0x391]; - else if (ch >= 0x2010 && ch <= 0x9fa0) - cp = from_ucs4_cjk[ch - 0x02010]; - else - break; - } - else - cp = from_ucs4_lat1[ch]; - */ - johab_from_ucs4 (ch, cp); - - if (cp[0] == '\0' && ch != 0) - /* Illegal character. */ - break; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_johab_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "JOHAB" +#define FROM_LOOP from_johab +#define TO_LOOP to_johab +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 + + +/* First define the conversion function from JOHAB to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + /* half-width Korean Currency WON sign \ + if (ch == 0x5c) \ + ch = 0x20a9; \ + else if (ch < 0x7f) \ + ch = (wchar_t) ch; \ + */ \ + if (ch < 0x7f) \ + /* Plain ASCII. */ \ + ++inptr; \ + /* Johab : 1. Hangul \ + 1st byte : 0x84-0xd3 \ + 2nd byte : 0x41-0x7e, 0x81-0xfe \ + 2. Hanja & Symbol : \ + 1st byte : 0xd8-0xde, 0xe0-0xf9 \ + 2nd byte : 0x31-0x7e, 0x91-0xfe \ + 0xd831-0xd87e and 0xd891-0xd8fe are user-defined area */ \ + else \ + { \ + if (ch > 0xf9 || ch == 0xdf || (ch > 0x7e && ch < 0x84) \ + || (ch > 0xd3 && ch < 0xd9)) \ + { \ + /* These are illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two-byte character. First test whether the next \ + character is also available. */ \ + uint32_t ch2; \ + uint_fast32_t idx; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. Store the \ + intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + idx = ch * 256 + ch2; \ + if (ch <= 0xd3) \ + { \ + /* Hangul */ \ + uint_fast32_t i, m, f; \ + \ + i = init[(idx & 0x7c00) >> 10]; \ + m = mid[(idx & 0x03e0) >> 5]; \ + f = final[idx & 0x001f]; \ + \ + if (i == -1 || m == -1 || f == -1) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else if (i > 0 && m > 0) \ + ch = ((i - 1) * 21 + (m - 1)) * 28 + f + 0xac00; \ + else if (i > 0 && m == 0 & f == 0) \ + ch = init_to_ucs[i - 1]; \ + else if (i == 0 && m > 0 & f == 0) \ + ch = 0x314e + m; /* 0x314f + m - 1 */ \ + else if (i == 0 && m == 0 & f > 0) \ + ch = final_to_ucs[f - 1]; /* round trip?? */ \ + else \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + else \ + { \ + if (ch2 < 0x31 || (ch2 > 0x7e && ch2 < 0x91) || ch2 == 0xff) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else if (ch == 0xda && ch2 > 0xa0 && ch2 < 0xd4) \ + { \ + /* This is illegal. Modern Hangul Jaso is defined \ + elsewhere in Johab */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + ch = johab_sym_hanja_to_ucs (idx, ch, ch2); \ + /* if (idx <= 0xdefe) \ + ch = __ksc5601_sym_to_ucs[(ch - 0xd9) * 192 \ + + ch2 - (ch2 > 0x90 \ + ? 0x43 : 0x31)]; \ + else \ + ch = __ksc5601_hanja_to_ucs[(ch - 0xe0) *192 \ + + ch2 - (ch2 > 0x90 \ + ?0x43 : 0x31)];\ + */ \ + } \ + } \ + } \ + \ + if (ch == 0) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + unsigned char cp[2]; \ + /* \ + if (ch >= (sizeof (from_ucs4_lat1) / sizeof (from_ucs4_lat1[0]))) \ + { \ + if (ch >= 0x0391 && ch <= 0x0451) \ + cp = from_ucs4_greek[ch - 0x391]; \ + else if (ch >= 0x2010 && ch <= 0x9fa0) \ + cp = from_ucs4_cjk[ch - 0x02010]; \ + else \ + break; \ + } \ + else \ + cp = from_ucs4_lat1[ch]; \ + */ \ + johab_from_ucs4 (ch, cp); \ + \ + if (cp[0] == '\0' && ch != 0) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *outptr++ = cp[0]; \ + /* Now test for a possible second byte and write this if possible. */ \ + if (cp[1] != '\0') \ + { \ + if (NEED_LENGTH_TEST && outptr >= outend) \ + { \ + /* The result does not fit into the buffer. */ \ + --outptr; \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + *outptr++ = cp[1]; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/koi-8.c b/iconvdata/koi-8.c index 2228456801..b2332c2a6a 100644 --- a/iconvdata/koi-8.c +++ b/iconvdata/koi-8.c @@ -1,5 +1,5 @@ /* Conversion from and to KOI-8. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Get the conversion table. */ +#include <stdint.h> #include <koi-8.h> -#define NAME "KOI-8" + +#define CHARSET_NAME "KOI-8" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-generic.c> diff --git a/iconvdata/koi8-r.c b/iconvdata/koi8-r.c index 502132b338..ee317bd25b 100644 --- a/iconvdata/koi8-r.c +++ b/iconvdata/koi8-r.c @@ -1,5 +1,5 @@ /* Conversion from and to KOI8-R. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,12 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> + +/* Specify the conversion table. */ #define TABLES <koi8-r.h> -#define NAME "KOI8-R" + +#define CHARSET_NAME "KOI8-R" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-gap.c> diff --git a/iconvdata/ksc5601.c b/iconvdata/ksc5601.c index c919425aa7..da64c430f4 100644 --- a/iconvdata/ksc5601.c +++ b/iconvdata/ksc5601.c @@ -18,7 +18,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +#include <stdint.h> #include "ksc5601.h" /* @@ -50,7 +50,7 @@ perl tab21.pl > ksc_hangul1.tb */ -const uint16_t ksc5601_hangul_to_ucs[KSC5601_HANGUL]= +const uint16_t __ksc5601_hangul_to_ucs[KSC5601_HANGUL]= { 0xac00, 0xac01, 0xac04, 0xac07, 0xac08, 0xac09, 0xac0a, 0xac10, 0xac11, 0xac12, 0xac13, 0xac14, 0xac15, 0xac16, 0xac17, 0xac19, @@ -369,7 +369,7 @@ grep -v '# HANGUL SYLLABLE' | perl tab11.pl > ksc_sym1.tb */ -const uint16_t ksc5601_sym_to_ucs[] = +const uint16_t __ksc5601_sym_to_ucs[] = { [0x0000] = 0x3000, [0x0001] = 0x3001, [0x0002] = 0x3002, [0x0003] = 0x00b7, [0x0004] = 0x2025, [0x0005] = 0x2026, [0x0006] = 0x00a8, [0x0007] = 0x3003, @@ -646,7 +646,7 @@ perl tab12.pl > ksc_sym2.tb */ -const uint16_t ksc5601_sym_from_ucs[KSC5601_SYMBOL][2] = +const uint16_t __ksc5601_sym_from_ucs[KSC5601_SYMBOL][2] = { {0x00a1, 0x222e}, {0x00a4, 0x2234}, {0x00a7, 0x2157}, {0x00a8, 0x2127}, {0x00aa, 0x2823}, {0x00ad, 0x2129}, {0x00b0, 0x2146}, {0x00b1, 0x213e}, @@ -914,7 +914,7 @@ perl tab21.pl > ksc_hanja1.tb printf ("\n"); */ -const uint16_t ksc5601_hanja_to_ucs[KSC5601_HANJA]= +const uint16_t __ksc5601_hanja_to_ucs[KSC5601_HANJA]= { 0x4f3d, 0x4f73, 0x5047, 0x50f9, 0x52a0, 0x53ef, 0x5475, 0x54e5, 0x5609, 0x5ac1, 0x5bb6, 0x6687, 0x67b6, 0x67b7, 0x67ef, 0x6b4c, @@ -1550,7 +1550,7 @@ awk '{print $2,$1}' | sort -u | perl tab12.pl > ksc_hanja2.tb */ -const uint16_t ksc5601_hanja_from_ucs[KSC5601_HANJA][2]= +const uint16_t __ksc5601_hanja_from_ucs[KSC5601_HANJA][2]= { {0x4e00, 0x6c69}, {0x4e01, 0x6f4b}, {0x4e03, 0x7652}, {0x4e07, 0x5832}, {0x4e08, 0x6d5b}, {0x4e09, 0x5f32}, {0x4e0a, 0x5f3e}, {0x4e0b, 0x793b}, diff --git a/iconvdata/ksc5601.h b/iconvdata/ksc5601.h index 0d86c7b253..8a5c40e5dd 100644 --- a/iconvdata/ksc5601.h +++ b/iconvdata/ksc5601.h @@ -28,18 +28,18 @@ #include <stdint.h> /* Conversion table. */ -extern const uint16_t ksc5601_hangul_to_ucs[KSC5601_HANGUL]; -extern const uint16_t ksc5601_sym_to_ucs[]; -extern const uint16_t ksc5601_sym_from_ucs[KSC5601_SYMBOL][2]; -extern const uint16_t ksc5601_hanja_to_ucs[KSC5601_HANJA]; -extern const uint16_t ksc5601_hanja_from_ucs[KSC5601_HANJA][2]; +extern const uint16_t __ksc5601_hangul_to_ucs[KSC5601_HANGUL]; +extern const uint16_t __ksc5601_sym_to_ucs[]; +extern const uint16_t __ksc5601_sym_from_ucs[KSC5601_SYMBOL][2]; +extern const uint16_t __ksc5601_hanja_to_ucs[KSC5601_HANJA]; +extern const uint16_t __ksc5601_hanja_from_ucs[KSC5601_HANJA][2]; /* static inline wchar_t ksc5601_to_ucs4 (char **s, size_t avail) */ -static inline wchar_t +static inline uint32_t ksc5601_to_ucs4 (uint16_t s) { unsigned char ch = s / 256; @@ -61,23 +61,25 @@ ksc5601_to_ucs4 (uint16_t s) Hangul in KS C 5601 : row 16 - row 40 */ if (idx >= 1410 && idx < 3760) - return ksc5601_hangul_to_ucs[idx-1410]; + return __ksc5601_hangul_to_ucs[idx-1410]; else if (idx > 3854) /* Hanja : row 42 - row 93 : 3854 = 94 * (42-1) */ - return ksc5601_hanja_to_ucs[idx-3854]; + return __ksc5601_hanja_to_ucs[idx-3854]; else - return ksc5601_sym_to_ucs[idx] ?: UNKNOWN_10646_CHAR; + return __ksc5601_sym_to_ucs[idx] ?: UNKNOWN_10646_CHAR; } static inline size_t -ucs4_to_ksc5601_hangul (wchar_t wch, uint16_t *s) +ucs4_to_ksc5601_hangul (uint32_t wch, uint16_t *s) { - int l=0,m,u=KSC5601_HANGUL-1; - wchar_t try; + int l = 0; + int m; + int u = KSC5601_HANGUL - 1; + uint32_t try; while (l <= u) { - try = (wchar_t) ksc5601_hangul_to_ucs[m=(l+u)/2]; + try = (uint32_t) __ksc5601_hangul_to_ucs[m=(l+u)/2]; if (try > wch) u = m - 1; else if (try < wch) @@ -93,21 +95,24 @@ ucs4_to_ksc5601_hangul (wchar_t wch, uint16_t *s) static inline size_t -ucs4_to_ksc5601_hanja (wchar_t wch, uint16_t *s) +ucs4_to_ksc5601_hanja (uint32_t wch, uint16_t *s) { - int l=0,m,u=KSC5601_HANJA-1; - wchar_t try; + int l = 0; + int m; + int u = KSC5601_HANJA - 1; + uint32_t try; while (l <= u) { - try = (wchar_t) ksc5601_hanja_from_ucs[m=(l+u)/2][0]; + m = (l + u) / 2; + try = (uint32_t) __ksc5601_hanja_from_ucs[m][0]; if (try > wch) u=m-1; else if (try < wch) l = m + 1; else { - *s = ksc5601_hanja_from_ucs[m][1]; + *s = __ksc5601_hanja_from_ucs[m][1]; return 2; } } @@ -115,24 +120,24 @@ ucs4_to_ksc5601_hanja (wchar_t wch, uint16_t *s) } static inline size_t -ucs4_to_ksc5601_sym (wchar_t wch, uint16_t *s) +ucs4_to_ksc5601_sym (uint32_t wch, uint16_t *s) { int l = 0; int m; int u = KSC5601_SYMBOL - 1; - wchar_t try; + uint32_t try; while (l <= u) { m = (l + u) / 2; - try = ksc5601_sym_from_ucs[m][0]; + try = __ksc5601_sym_from_ucs[m][0]; if (try > wch) u = m - 1; else if (try < wch) l = m + 1; else { - *s = ksc5601_sym_from_ucs[m][1]; + *s = __ksc5601_sym_from_ucs[m][1]; return 2; } } @@ -146,13 +151,13 @@ ucs4_to_ksc5601 (wchar_t wch, char **s, size_t avail) */ static inline size_t -ucs4_to_ksc5601 (wchar_t ch, uint16_t *s) +ucs4_to_ksc5601 (uint32_t ch, uint16_t *s) { *s = (uint16_t) UNKNOWN_10646_CHAR; /* FIXIT */ if (ch >= 0xac00 && ch <= 0xd7a3) return ucs4_to_ksc5601_hangul (ch, s); - else if (ch >= 0x4e00 && ch <= 0x9fff || ch >= 0xf900 && ch <= 0xfa0b) + else if (ch >= 0x4e00 && ch <= 0x9fff || ch >= 0xf900 && ch <= 0xfa0b) return ucs4_to_ksc5601_hanja (ch, s); else return ucs4_to_ksc5601_sym (ch, s); diff --git a/iconvdata/latin-greek-1.c b/iconvdata/latin-greek-1.c index d62969a77d..37ccf09c09 100644 --- a/iconvdata/latin-greek-1.c +++ b/iconvdata/latin-greek-1.c @@ -1,5 +1,5 @@ /* Conversion from and to LATIN-GREEK-1. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Specify the conversion table. */ #define TABLES <latin-greek-1.h> -#define NAME "LATIN-GREEK-1" + +#define CHARSET_NAME "LATIN-GREEK-1" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-gap.c> diff --git a/iconvdata/latin-greek.c b/iconvdata/latin-greek.c index 90270e0e07..8810f4a2e0 100644 --- a/iconvdata/latin-greek.c +++ b/iconvdata/latin-greek.c @@ -1,5 +1,5 @@ /* Conversion from and to LATIN-GREEK. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -18,7 +18,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <wchar.h> +/* Specify the conversion table. */ #define TABLES <latin-greek.h> -#define NAME "LATIN-GREEK" + +#define CHARSET_NAME "LATIN-GREEK" +#define HAS_HOLES 1 /* Not all 256 character are defined. */ + #include <8bit-gap.c> diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh index ebafa2f298..af6a136c4a 100755 --- a/iconvdata/run-iconv-test.sh +++ b/iconvdata/run-iconv-test.sh @@ -52,10 +52,18 @@ while read from to targets; do { echo "*** conversion from $t to $to failed"; exit 1; } test -s $temp1 && cmp testdata/$from $temp2 >& /dev/null || { echo "*** $from -> t -> $to conversion failed"; exit 1; } + rm -f $temp1 $temp2 + + # Now test some bigger text, entirely in ASCII. + $ICONV -f $from -t $t testdata/suntzus | + $ICONV -f $t -t $to > $temp1 || + { echo "*** conversion $from->$t->$to of suntzus failed"; exit 1; } + cmp testdata/suntzus.txt $temp1 || + { echo "*** conversion $from->$t->$to of suntzus incorrect"; exit 1; } + rm -f $temp1 # All tests ok. echo "$from -> $t -> $to ok" - rm -f $temp1 $temp2 done done < TESTS diff --git a/iconvdata/sjis.c b/iconvdata/sjis.c index 33dc2f1d65..d65b905b32 100644 --- a/iconvdata/sjis.c +++ b/iconvdata/sjis.c @@ -18,12 +18,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <string.h> #include <wchar.h> -static const wchar_t halfkana_to_ucs4[] = +static const uint32_t halfkana_to_ucs4[] = { 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, 0xff70, @@ -3981,268 +3979,151 @@ static const char from_ucs4_cjk[32657][2] = }; -/* Direction of the transformation. */ -static int to_sjis_object; -static int from_sjis_object; +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "SJIS" +#define FROM_LOOP from_sjis +#define TO_LOOP to_sjis +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 +/* First define the conversion function from SJIS to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch == 0x5c) \ + { \ + ch = 0xa5; \ + ++inptr; \ + } \ + else if (ch == 0x7e) \ + { \ + ch = 0x203e; \ + ++inptr; \ + } \ + else if (ch < 0x7e) \ + ++inptr; \ + else if (ch >= 0xa1 && ch <= 0xdf) \ + { \ + ch = halfkana_to_ucs4[ch - 0xa1]; \ + ++inptr; \ + } \ + else if (ch > 0xea || ch == 0xa0 || ch == 0x7f || ch == 0x80) \ + { \ + /* These are illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two-byte character. First test whether the next character \ + is also available. */ \ + uint32_t ch2; \ + uint_fast32_t idx; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. Store \ + the intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + idx = ch * 256 + ch2; \ + if (idx < 0x8140 || (idx > 0x84be && idx < 0x889f) \ + || (idx > 0x89fc && idx < 0x9040) \ + || (idx > 0x9ffc && idx < 0xe040) || idx > 0xeaa4) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* We could pack the data a bit more dense. The second \ + byte will never be 0x7f and it will also be never \ + >0xfc. But this would mean yet more `if's. */ \ + if (idx <= 0x84be) \ + ch = cjk_block1[(ch - 0x81) * 192 + ch2 - 0x40]; \ + else if (idx <= 0x89fc) \ + ch = cjk_block2[(ch - 0x88) * 192 + ch2 - 0x9f]; \ + else if (idx <= 0x9ffc) \ + ch = cjk_block3[(ch - 0x90) * 192 + ch2 - 0x40]; \ + else \ + ch = cjk_block4[(ch - 0xe0) * 192 + ch2 - 0x40]; \ + } \ + \ + if (ch == 0) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "SJIS") != NULL) - step->data = &from_sjis_object; - else if (strcasestr (step->to_name, "SJIS") != NULL) - step->data = &to_sjis_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_sjis_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = inbuf[cnt]; - wchar_t ch; - - if (inchar == 0x5c) - ch = L'\xa5'; - else if (inchar == 0x7e) - ch = 0x203e; - else if (inchar < 0x7e) - ch = (wchar_t) inchar; - else if (inchar >= 0xa1 && inchar <= 0xdf) - ch = halfkana_to_ucs4[inchar - 0xa1]; - else if (inchar > 0xea || inchar == 0xa0 || inchar == 0x7f - || inchar == 0x80) - /* These are illegal. */ - ch = L'\0'; - else - { - /* Two-byte character. First test whether the next - character is also available. */ - int inchar2; - int idx; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = inbuf[++cnt]; - idx = inchar * 256 + inchar2; - if (idx < 0x8140 || (idx > 0x84be && idx < 0x889f) - || (idx > 0x89fc && idx < 0x9040) - || (idx > 0x9ffc && idx < 0xe040) || idx > 0xeaa4) - /* This is illegal. */ - ch = L'\0'; - else - { - /* We could pack the data a bit more dense. - The second byte will never be 0x7f and it - will also be never >0xfc. But this would - mean yet more `if's. */ - if (idx <= 0x84be) - ch = cjk_block1[(inchar - 0x81) * 192 - + inchar2 - 0x40]; - else if (idx <= 0x89fc) - ch = cjk_block2[(inchar - 0x88) * 192 - + inchar2 - 0x9f]; - else if (idx <= 0x9ffc) - ch = cjk_block3[(inchar - 0x90) * 192 - + inchar2 - 0x40]; - else - ch = cjk_block4[(inchar - 0xe0) * 192 - + inchar2 - 0x40]; - } - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - int ch = *((wchar_t *) (inbuf + cnt)); - const char *cp; - - if (ch >= (sizeof (from_ucs4_lat1) - / sizeof (from_ucs4_lat1[0]))) - { - if (ch >= 0x0391 && ch <= 0x0451) - cp = from_ucs4_greek[ch - 0x391]; - else if (ch >= 0x2010 && ch <= 0x9fa0) - cp = from_ucs4_cjk[ch - 0x02010]; - else - /* Illegal character. */ - break; - } - else - cp = from_ucs4_lat1[ch]; - - if (cp[0] == '\0' && ch != 0) - /* Illegal character. */ - break; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_sjis_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + const char *cp; \ + \ + if (ch >= (sizeof (from_ucs4_lat1) / sizeof (from_ucs4_lat1[0]))) \ + { \ + if (ch >= 0x0391 && ch <= 0x0451) \ + cp = from_ucs4_greek[ch - 0x391]; \ + else if (ch >= 0x2010 && ch <= 0x9fa0) \ + cp = from_ucs4_cjk[ch - 0x02010]; \ + else \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + else \ + cp = from_ucs4_lat1[ch]; \ + \ + if (cp[0] == '\0' && ch != 0) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *outptr++ = cp[0]; \ + /* Now test for a possible second byte and write this if possible. */ \ + if (cp[1] != '\0') \ + { \ + if (NEED_LENGTH_TEST && outptr >= outend) \ + { \ + /* The result does not fit into the buffer. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + *outptr++ = cp[1]; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> - if (written != NULL && data->is_last) - *written = do_write; - return result; -} +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/t61.c b/iconvdata/t61.c index b77ee71248..8c288adca2 100644 --- a/iconvdata/t61.c +++ b/iconvdata/t61.c @@ -19,6 +19,7 @@ Boston, MA 02111-1307, USA. */ #include <gconv.h> +#include <stdint.h> #include <string.h> /* Data taken from the WG15 tables. */ @@ -362,248 +363,133 @@ static const char from_ucs4[][2] = */ }; -/* Direction of the transformation. */ -static int to_t61_object; -static int from_t61_object; +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "T.61" +#define FROM_LOOP from_t_61 +#define TO_LOOP to_t_61 +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 + +/* First define the conversion function from T.61 to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = *inptr; \ + \ + if (ch >= 0xc1 && ch <= 0xcf) \ + { \ + /* Composed character. First test whether the next character \ + is also available. */ \ + uint32_t ch2; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + \ + if (ch2 < 0x20 || ch2 >= 0x80) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20]; \ + \ + inptr += 2; \ + } \ + else \ + { \ + ch = to_ucs4[ch]; \ + ++inptr; \ + } \ + \ + if (ch == 0 && *inptr != '\0') \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + char tmp[2]; \ + uint32_t ch = *((uint32_t *) inptr); \ + const char *cp; \ + \ + if (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0])) \ + { \ + if (ch == 0x2126) \ + cp = "\xe0"; \ + else if (ch == 0x2c7) \ + cp = "\xcf\x20"; \ + else if (ch < 0x2d8 || ch > 0x2dd) \ + { \ + /* Illegal characters. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + static const char map[5] = "\xc6\xc7\xca\xce\xcd"; \ + \ + tmp[0] = map[ch - 0x2d8]; \ + tmp[1] = ' '; \ + cp = tmp; \ + } \ + } \ + else \ + { \ + cp = from_ucs4[ch]; \ + \ + if (cp[0] == '\0' && ch != 0) \ + { \ + /* Illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + \ + *outptr++ = cp[0]; \ + /* Now test for a possible second byte and write this if possible. */ \ + if (cp[1] != '\0') \ + { \ + if (NEED_LENGTH_TEST && outptr >= outend) \ + { \ + /* The result does not fit into the buffer. */ \ + --outptr; \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + *outptr++ = cp[1]; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "T.61") != NULL) - step->data = &from_t61_object; - else if (strcasestr (step->to_name, "T.61") != NULL) - step->data = &to_t61_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_t61_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = inbuf[cnt]; - wchar_t ch; - - if (inchar >= '\xc1' && inchar <= '\xcf') - { - /* Composed character. First test whether the next - character is also available. */ - int inchar2; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = inbuf[++cnt]; - - if (inchar2 < '\x20' || inchar2 >= '\x80') - /* This is illegal. */ - ch = L'\0'; - else - ch = to_ucs4_comb[inchar - 0xc1][inchar2 - 0x20]; - - if (ch == L'\0') - /* Undo the increment for illegal characters. */ - --cnt; - } - else - ch = to_ucs4[inchar]; - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - char tmp[2]; - int ch = *((wchar_t *) (inbuf + cnt)); - const char *cp; - - if (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0])) - { - if (ch == 0x2126) - cp = "\xe0"; - else if (ch == 0x2c7) - cp = "\xcf\x20"; - else if (ch < 0x2d8 || ch > 0x2dd) - /* Illegal characters. */ - break; - else - { - static const char map[5] = "\xc6\xc7\xca\xce\xcd"; - - tmp[0] = map[ch - 0x2d8]; - tmp[1] = ' '; - cp = tmp; - } - } - else if (ch < 0 || (from_ucs4[ch][0] == '\0' && ch != 0)) - break; - else - cp = from_ucs4[ch]; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_t61_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - return result; -} +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/iconvdata/uhc.c b/iconvdata/uhc.c index ed4b7adb70..f3addd4c4d 100644 --- a/iconvdata/uhc.c +++ b/iconvdata/uhc.c @@ -18,16 +18,9 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <gconv.h> #include <stdint.h> -#include <string.h> -#include <wchar.h> #include <ksc5601.h> -/* Direction of the transformation. */ -static int to_uhc_object; -static int from_uhc_object; - /* egrep \ @@ -2576,20 +2569,20 @@ static const uint16_t uhc_hangul_from_ucs[11172]= 0xc64f, 0xc650, 0xc651, 0xc652 }; + static inline void -uhc_from_ucs4(wchar_t ch, unsigned char *cp) +uhc_from_ucs4 (uint32_t ch, unsigned char *cp) { if (ch >= 0x7f) { uint16_t idx=0; if (ch >= 0xac00 && ch <= 0xd7a3) - idx = uhc_hangul_from_ucs[(int) ch - 0xac00]; - else if (ch >= 0x4e00 && ch <= 0x9fa5 - || ch >= 0xf900 && ch <= 0xfa0b) + idx = uhc_hangul_from_ucs[ch - 0xac00]; + else if (ch >= 0x4e00 && ch <= 0x9fa5 || ch >= 0xf900 && ch <= 0xfa0b) { ucs4_to_ksc5601_hanja (ch,&idx); - idx |= (idx ? 0x8080 : 0); + idx |= (idx ? 0x8080 : 0); } /* Half-width Korean Currency Won Sign else if (ch == 0x20a9) @@ -2598,286 +2591,169 @@ uhc_from_ucs4(wchar_t ch, unsigned char *cp) else { ucs4_to_ksc5601_sym (ch, &idx); - idx |= (idx ? 0x8080 : 0); + idx |= (idx ? 0x8080 : 0); } - *cp = (char) (idx / 256); - *(cp + 1) = (char) (idx & 0xff) ; + cp[0] = (unsigned char) (idx / 256); + cp[1] = (unsigned char) (idx & 0xff); } - /* think about 0x5c ; '\' */ + /* XXX Think about 0x5c ; '\'. */ else { - *cp = (char) (0x7f & ch) ; - *(cp + 1) = (char) 0; + cp[0] = (unsigned char) ch; + cp[1] = (unsigned char) 0; } } -int -gconv_init (struct gconv_step *step) -{ - /* Determine which direction. */ - if (strcasestr (step->from_name, "UHC") != NULL) - step->data = &from_uhc_object; - else if (strcasestr (step->to_name, "UHC") != NULL) - step->data = &to_uhc_object; - else - return GCONV_NOCONV; - - return GCONV_OK; -} - - -void -gconv_end (struct gconv_step *data) -{ - /* Nothing to do. */ -} - - -int -gconv (struct gconv_step *step, struct gconv_step_data *data, - const char *inbuf, size_t *inbufsize, size_t *written, int do_flush) -{ - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - gconv_fct fct = next_step->fct; - size_t do_write; - int result; - - /* If the function is called with no input this means we have to reset - to the initial state. The possibly partly converted input is - dropped. */ - if (do_flush) - { - do_write = 0; - - /* Call the steps down the chain if there are any. */ - if (data->is_last) - result = GCONV_OK; - else - { - struct gconv_step *next_step = step + 1; - struct gconv_step_data *next_data = data + 1; - - result = (*fct) (next_step, next_data, NULL, 0, written, 1); - - /* Clear output buffer. */ - data->outbufavail = 0; - } - } - else - { - do_write = 0; - - do - { - result = GCONV_OK; - - if (step->data == &from_uhc_object) - { - size_t inchars = *inbufsize; - size_t outwchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - - while (cnt < inchars - && (outwchars + sizeof (wchar_t) <= data->outbufsize)) - { - int inchar = (unsigned char) inbuf[cnt]; - wchar_t ch; -/* half-width Korean Currency WON sign - - if (inchar == 0x5c) - ch = 0x20a9; - else if (inchar <= 0x7f) - ch = (wchar_t) inchar; -*/ - if (inchar <= 0x7f) - ch = (wchar_t) inchar; - - - else if ( inchar <= 0x80 || inchar >= 0xfe || inchar == 0xc9) - /* This is illegal. */ - ch = L'\0'; - else - { - /* Two-byte character. First test whether the next - character is also available. */ - int inchar2; - - if (cnt + 1 >= inchars) - { - /* The second character is not available. Store - the intermediate result. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - - inchar2 = (unsigned char) inbuf[++cnt]; - -/* - Additional code points not present in EUC-KR - - 1st byte 2nd byte - 0x81-0xa0 0x41-0x5a, 0x61-0x7a, 0x81-0xfe total - (32) (26) + (26) + (126) = 178 5696 - - 0xa1-0xc5 0x41-0x5a 0x61-0x7a 0x81-0xa0 - (37) (26) + (26) + (32) = 84 3108 - - 0xc6 0x41-0x52 - (1) (18) 18 - - 8822 - - - 8822(only in UHC) + 2350(both in EUC-KR and UHC) = 11,172 -*/ - - if ( inchar < 0xa1 || inchar2 < 0xa1) - if ( inchar > 0xc6 || inchar2 <0x41 || - inchar2 > 0x5a && inchar2 < 0x61 || - inchar2 > 0x7a && inchar2 < 0x81 || - inchar == 0xc6 && inchar2 > 0x52 ) - ch = L'0'; - else - { - ch = uhc_extra_to_ucs[ inchar2 - 0x41 - - ( inchar2 > 0x80 ? 12 : - ( inchar2 > 0x60 ? 6 : 0 ) ) - + ( inchar < 0xa1 ? - (inchar - 0x81) * 178 : - 5696 + (inchar - 0xa1) * 84 ) ] ; - } - - else - if ( ( ch = ksc5601_to_ucs4( - (uint16_t) (inchar * 256 + inchar2) & 0x7f7f) ) - == UNKNOWN_10646_CHAR ) - - ch = L'\0'; - - if (ch == L'\0') - --cnt; - } - - if (ch == L'\0' && inbuf[cnt] != '\0') - { - /* This is an illegal character. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - - *((wchar_t *) (outbuf + outwchars)) = ch; - ++do_write; - outwchars += sizeof (wchar_t); - ++cnt; - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outwchars; - } - else - { - size_t inwchars = *inbufsize; - size_t outchars = data->outbufavail; - char *outbuf = data->outbuf; - size_t cnt = 0; - int extra = 0; - - while (inwchars >= cnt + sizeof (wchar_t) - && outchars < data->outbufsize) - { - wchar_t ch = *((wchar_t *) (inbuf + cnt)); - unsigned char cp[2]; - - uhc_from_ucs4(ch,cp) ; - - if (cp[0] == '\0' && ch != 0) - /* Illegal character. */ - break; - - outbuf[outchars] = cp[0]; - /* Now test for a possible second byte and write this - if possible. */ - if (cp[1] != '\0') - { - if (outchars + 1 >= data->outbufsize) - { - /* The result does not fit into the buffer. */ - extra = 1; - break; - } - outbuf[++outchars] = cp[1]; - } - - ++do_write; - ++outchars; - cnt += sizeof (wchar_t); - } - *inbufsize -= cnt; - inbuf += cnt; - data->outbufavail = outchars; - - if (outchars + extra < data->outbufsize) - { - /* If there is still room in the output buffer something - is wrong with the input. */ - if (inwchars >= cnt + sizeof (wchar_t)) - { - /* An error occurred. */ - result = GCONV_ILLEGAL_INPUT; - break; - } - if (inwchars != cnt) - { - /* There are some unprocessed bytes at the end of the - input buffer. */ - result = GCONV_INCOMPLETE_INPUT; - break; - } - } - } - - if (result != GCONV_OK) - break; - - if (data->is_last) - { - /* This is the last step. */ - result = (*inbufsize > (step->data == &from_uhc_object - ? 0 : sizeof (wchar_t) - 1) - ? GCONV_FULL_OUTPUT : GCONV_EMPTY_INPUT); - break; - } - - /* Status so far. */ - result = GCONV_EMPTY_INPUT; - - if (data->outbufavail > 0) - { - /* Call the functions below in the chain. */ - size_t newavail = data->outbufavail; - - result = (*fct) (next_step, next_data, data->outbuf, &newavail, - written, 0); - - /* Correct the output buffer. */ - if (newavail != data->outbufavail && newavail > 0) - { - memmove (data->outbuf, - &data->outbuf[data->outbufavail - newavail], - newavail); - data->outbufavail = newavail; - } - } - } - while (*inbufsize > 0 && result == GCONV_EMPTY_INPUT); - } - - if (written != NULL && data->is_last) - *written = do_write; - - return result; -} +/* Definitions used in the body of the `gconv' function. */ +#define CHARSET_NAME "UHC" +#define FROM_LOOP from_uhc +#define TO_LOOP to_uhc +#define DEFINE_INIT 1 +#define DEFINE_FINI 1 +#define MIN_NEEDED_FROM 1 +#define MAX_NEEDED_FROM 2 +#define MIN_NEEDED_TO 4 + +/* First define the conversion function from UHC to UCS4. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_FROM +#define MAX_NEEDED_INPUT MAX_NEEDED_FROM +#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +#define LOOPFCT FROM_LOOP +#define BODY \ + { \ + uint32_t ch = (uint32_t) *inptr; \ + \ +/* half-width Korean Currency WON sign \ + \ + if (ch == 0x5c) \ + ch = 0x20a9; \ + else if (ch <= 0x7f) \ + ch = (wchar_t) ch; \ +*/ \ + if (ch <= 0x7f) \ + ++inptr; \ + else if (ch <= 0x80 || ch >= 0xfe || ch == 0xc9) \ + { \ + /* This is illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + else \ + { \ + /* Two-byte character. First test whether the next character \ + is also available. */ \ + uint32_t ch2; \ + \ + if (NEED_LENGTH_TEST && inptr + 1 >= inend) \ + { \ + /* The second character is not available. Store \ + the intermediate result. */ \ + result = GCONV_INCOMPLETE_INPUT; \ + break; \ + } \ + \ + ch2 = inptr[1]; \ + \ +/* \ + Additional code points not present in EUC-KR \ + \ + 1st byte 2nd byte \ + 0x81-0xa0 0x41-0x5a, 0x61-0x7a, 0x81-0xfe total \ + (32) (26) + (26) + (126) = 178 5696 \ + \ + 0xa1-0xc5 0x41-0x5a 0x61-0x7a 0x81-0xa0 \ + (37) (26) + (26) + (32) = 84 3108 \ + \ + 0xc6 0x41-0x52 \ + (1) (18) 18 \ + \ + 8822 \ + \ + 8822(only in UHC) + 2350(both in EUC-KR and UHC) = 11,172 \ +*/ \ + \ + if (ch < 0xa1 || ch2 < 0xa1) \ + { \ + if (ch > 0xc6 || ch2 <0x41 || (ch2 > 0x5a && ch2 < 0x61) \ + || (ch2 > 0x7a && ch2 < 0x81) || (ch == 0xc6 && ch2 > 0x52)) \ + { \ + /* This is not legal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + ch = uhc_extra_to_ucs[ch2 - 0x41 \ + - (ch2 > 0x80 ? 12 : (ch2 > 0x60 ? 6 : 0)) \ + + (ch < 0xa1 \ + ? (ch - 0x81) * 178 \ + : 5696 + (ch - 0xa1) * 84)]; \ + } \ + else \ + { \ + ch = ksc5601_to_ucs4 ((ch * 256 + ch2) & 0x7f7f); \ + \ + if (ch == UNKNOWN_10646_CHAR) \ + { \ + /* Illegal. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + } \ + \ + if (ch == 0) \ + { \ + /* This is an illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + inptr += 2; \ + } \ + \ + *((uint32_t *) outptr)++ = ch; \ + } +#include <iconv/loop.c> + + +/* Next, define the other direction. */ +#define MIN_NEEDED_INPUT MIN_NEEDED_TO +#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +#define LOOPFCT TO_LOOP +#define BODY \ + { \ + uint32_t ch = *((uint32_t *) inptr); \ + unsigned char cp[2]; \ + \ + uhc_from_ucs4 (ch, cp); \ + \ + if (cp[0] == '\0' && ch != 0) \ + { \ + /* Illegal character. */ \ + result = GCONV_ILLEGAL_INPUT; \ + break; \ + } \ + \ + *outptr++ = cp[0]; \ + /* Now test for a possible second byte and write this if possible. */ \ + if (cp[1] != '\0') \ + { \ + if (NEED_LENGTH_TEST && outptr >= outend) \ + { \ + /* The result does not fit into the buffer. */ \ + result = GCONV_FULL_OUTPUT; \ + break; \ + } \ + \ + *outptr++ = cp[1]; \ + } \ + \ + inptr += 4; \ + } +#include <iconv/loop.c> + + +/* Now define the toplevel functions. */ +#include <iconv/skeleton.c> diff --git a/inet/netinet/in.h b/inet/netinet/in.h index ff8476e5c7..c6985ffa0a 100644 --- a/inet/netinet/in.h +++ b/inet/netinet/in.h @@ -277,6 +277,22 @@ extern uint16_t htons __P ((uint16_t __hostshort)); extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sock_in)); + +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((u_int8_t *) (a))[1] & 0xf) == 0x1)) + +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((u_int8_t *) (a))[1] & 0xf) == 0x2)) + +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((u_int8_t *) (a))[1] & 0xf) == 0x5)) + +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((u_int8_t *) (a))[1] & 0xf) == 0x8)) + +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((u_int8_t *) (a))[1] & 0xf) == 0xe)) + /* IPv6 packet information. */ struct in6_pktinfo { @@ -100,11 +100,12 @@ GLIBC_2.0 { __vsscanf; __vfscanf; __vsnprintf; _rpc_dtablesize; _null_auth; _seterr_reply; __res_randomid; __getpid; - __strcasecmp; __write; _strerror_internal; _dl_sysdep_output; + __strcasecmp; __strerror_r; __write; _dl_sysdep_output; _dl_debug_message; __ffs; __close; __connect; __fcntl; __lseek; __open; __read; __send; __wait; __ieee_get_fp_control; __ieee_set_fp_control; + __dgettext; # Exception handling support functions from libgcc __register_frame; __register_frame_table; __deregister_frame; @@ -440,13 +441,14 @@ GLIBC_2.1 { __signbit; __signbitf; __signbitl; __libc_sa_len; # functions used in other libraries - _IO_fclose; _IO_fopen; _IO_fdopen; __asprintf; + _IO_fclose; _IO_fopen; _IO_fdopen; __asprintf; __strcasestr; __syscall_rt_sigqueueinfo; __xstat64; __fxstat64; __lxstat64; __pread64; __pwrite64; # helper functions __libc_current_sigrtmin; __libc_current_sigrtmax; __libc_allocate_rtsig; + __libc_longjmp; __libc_siglongjmp; # Since we have new signals this structure changed. _sys_siglist; sys_siglist; sys_sigabbrev; diff --git a/libio/fileops.c b/libio/fileops.c index 7e60f7c8df..e5ffb245aa 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -48,7 +48,6 @@ extern int errno; # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence) # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes) # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes) -# define fstat(FD, Buf) __fxstat (_STAT_VER, FD, Buf) #endif /* An fstream can be in at most one of put mode, get mode, or putback mode. diff --git a/libio/oldfileops.c b/libio/oldfileops.c index 41fbc692e8..7cf4fdf22c 100644 --- a/libio/oldfileops.c +++ b/libio/oldfileops.c @@ -483,7 +483,7 @@ _IO_old_file_seekoff (fp, offset, dir, mode) break; case _IO_seek_end: { - struct stat st; + struct _G_stat64 st; if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode)) { offset += st.st_size; diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 7913e085f1..ba2a20f4d0 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,14 @@ +1998-04-20 14:55 Ulrich Drepper <drepper@cygnus.com> + + * Makefile (libpthread-routines): Add ptlongjmp and spinlock. + * internals.h: Add definitions for new spinlock implementation. + * ptlongjmp.c: New file. + * spinlock.c: New file. + * spinlock.h (acquire): Don't reschedule using __sched_yield, use + new function __pthread_acquire to prevent deadlocks with thread + with different priorities. + Patches by Xavier Leroy <Xavier.Leroy@inria.fr>. + 1998-03-16 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * manager.c (__pthread_manager): Reduce first argument to select diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile index 8813ae110f..cdfe06c66e 100644 --- a/linuxthreads/Makefile +++ b/linuxthreads/Makefile @@ -32,8 +32,8 @@ extra-libs := libpthread extra-libs-others := $(extra-libs) libpthread-routines := attr cancel condvar join manager mutex ptfork \ - pthread signals specific errno lockfile \ - semaphore wrapsyscall rwlock + ptlongjmp pthread signals specific errno lockfile \ + semaphore spinlock wrapsyscall rwlock libpthread-map := libpthread.map include ../Rules diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h index 0649e0d460..c56829684e 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -250,6 +250,23 @@ static inline pthread_descr thread_self (void) #endif } +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + With the 2.0 and 2.1 kernels, this MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + /* Debugging */ #ifdef DEBUG diff --git a/linuxthreads/ptlongjmp.c b/linuxthreads/ptlongjmp.c new file mode 100644 index 0000000000..1397dba43a --- /dev/null +++ b/linuxthreads/ptlongjmp.c @@ -0,0 +1,44 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#include <setjmp.h> +#include "pthread.h" +#include "internals.h" + +static void pthread_cleanup_upto(__jmp_buf target) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + + for (c = self->p_cleanup; + c != NULL && _JMPBUF_UNWINDS(target, c); + c = c->prev) + c->routine(c->arg); + self->p_cleanup = c; +} + +void siglongjmp(sigjmp_buf env, int val) +{ + pthread_cleanup_upto(env->__jmpbuf); + __libc_siglongjmp(env, val); +} + +void longjmp(jmp_buf env, int val) +{ + pthread_cleanup_upto(env->__jmpbuf); + __libc_longjmp(env, val); +} diff --git a/linuxthreads/spinlock.c b/linuxthreads/spinlock.c new file mode 100644 index 0000000000..170d9ae8d0 --- /dev/null +++ b/linuxthreads/spinlock.c @@ -0,0 +1,59 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Spin locks */ + +#include <sched.h> +#include <time.h> +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" + +/* This function is called if the inlined test-and-set in acquire() failed */ + +/* The retry strategy is as follows: + - We test and set the spinlock MAX_SPIN_COUNT times, calling + sched_yield() each time. This gives ample opportunity for other + threads with priority >= our priority to make progress and + release the spinlock. + - If a thread with priority < our priority owns the spinlock, + calling sched_yield() repeatedly is useless, since we're preventing + the owning thread from making progress and releasing the spinlock. + So, after MAX_SPIN_LOCK attemps, we suspend the calling thread + using nanosleep(). This again should give time to the owning thread + for releasing the spinlock. + Notice that the nanosleep() interval must not be too small, + since the kernel does busy-waiting for short intervals in a realtime + process (!). The smallest duration that guarantees thread + suspension is currently 2ms. + - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT + sched_yield(), then sleeping again if needed. */ + +void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + while (testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + nanosleep(&tm, NULL); + cnt = 0; + } + } +} diff --git a/linuxthreads/spinlock.h b/linuxthreads/spinlock.h index d324abbc84..1707d3e42a 100644 --- a/linuxthreads/spinlock.h +++ b/linuxthreads/spinlock.h @@ -15,9 +15,11 @@ /* Spin locks */ +extern void __pthread_acquire(int * spinlock); + static inline void acquire(int * spinlock) { - while (testandset(spinlock)) __sched_yield(); + if (testandset(spinlock)) __pthread_acquire(spinlock); } static inline void release(int * spinlock) diff --git a/login/Makefile b/login/Makefile index 5f7861b61c..96c75f7b4a 100644 --- a/login/Makefile +++ b/login/Makefile @@ -22,7 +22,7 @@ subdir := login -headers := utmp.h bits/utmp.h utmpx.h bits/utmpx.h lastlog.h pty.h +headers := utmp.h bits/utmp.h lastlog.h pty.h routines := getutent getutent_r getutid getutline getutid_r getutline_r \ utmp_file utmp_daemon utmpname updwtmp \ diff --git a/login/getutent.c b/login/getutent.c index eb99158592..51e147586e 100644 --- a/login/getutent.c +++ b/login/getutent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -35,4 +35,3 @@ __getutent (void) return result; } weak_alias (__getutent, getutent) -weak_alias (__getutent, getutxent) diff --git a/login/getutent_r.c b/login/getutent_r.c index 96c458f3a3..8391331cd5 100644 --- a/login/getutent_r.c +++ b/login/getutent_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com> and Paul Janzen <pcj@primenet.com>, 1996. @@ -143,7 +143,6 @@ __setutent (void) __libc_lock_unlock (__libc_utmp_lock); } weak_alias (__setutent, setutent) -weak_alias (__setutent, setutxent) int @@ -176,7 +175,6 @@ __pututline (const struct utmp *data) return buffer; } weak_alias (__pututline, pututline) -weak_alias (__pututline, pututxline) void @@ -190,4 +188,3 @@ __endutent (void) __libc_lock_unlock (__libc_utmp_lock); } weak_alias (__endutent, endutent) -weak_alias (__endutent, endutxent) diff --git a/login/getutid.c b/login/getutid.c index 98e8e4adc3..91e3ea20ac 100644 --- a/login/getutid.c +++ b/login/getutid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -35,4 +35,3 @@ __getutid (const struct utmp *id) return result; } weak_alias (__getutid, getutid) -weak_alias (__getutid, getutxid) diff --git a/login/getutline.c b/login/getutline.c index 1e1ecb1ce3..7fc402ffdd 100644 --- a/login/getutline.c +++ b/login/getutline.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -35,4 +35,3 @@ __getutline (const struct utmp *line) return result; } weak_alias (__getutline, getutline) -weak_alias (__getutline, getutxline) diff --git a/login/utmp.h b/login/utmp.h index 82f3fcce9a..ccf29b27ad 100644 --- a/login/utmp.h +++ b/login/utmp.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -53,6 +53,8 @@ extern void logwtmp __P ((__const char *__ut_line, __const char *__ut_name, __const char *__ut_host)); /* Append entry UTMP to the wtmp-like file WTMP_FILE. */ +extern void __updwtmp __P ((__const char *__wtmp_file, + __const struct utmp *__utmp)); extern void updwtmp __P ((__const char *__wtmp_file, __const struct utmp *__utmp)); @@ -61,6 +63,7 @@ extern int __utmpname __P ((__const char *__file)); extern int utmpname __P ((__const char *__file)); /* Read next entry from a utmp-like file. */ +extern struct utmp *__getutent __P ((void)); extern struct utmp *getutent __P ((void)); /* Reset the input stream to the beginning of the file. */ @@ -73,13 +76,16 @@ extern void endutent __P ((void)); /* Search forward from the current point in the utmp file until the next entry with a ut_type matching ID->ut_type. */ +extern struct utmp *__getutid __P ((__const struct utmp *__id)); extern struct utmp *getutid __P ((__const struct utmp *__id)); /* Search forward from the current point in the utmp file until the next entry with a ut_line matching LINE->ut_line. */ +extern struct utmp *__getutline __P ((__const struct utmp *__line)); extern struct utmp *getutline __P ((__const struct utmp *__line)); /* Write out entry pointed to by UTMP_PTR into the utmp file. */ +extern struct utmp *__pututline __P ((__const struct utmp *__utmp_ptr)); extern struct utmp *pututline __P ((__const struct utmp *__utmp_ptr)); diff --git a/manual/creature.texi b/manual/creature.texi index 66e53aceb4..00e3aada90 100644 --- a/manual/creature.texi +++ b/manual/creature.texi @@ -151,7 +151,7 @@ not generally used (see @code{_FILE_OFFSET_BITS}. @comment (NONE) @comment X/Open -@defvr _FILE_OFFSET_BITS +@defvr Macro _FILE_OFFSET_BITS This macro lets decide which file system interface shall be used, one replacing the other. While @code{_LARGEFILE64_SOURCE} makes the @w{64 bit} interface available as an additional interface diff --git a/posix/getopt.c b/posix/getopt.c index 7afe6c4a96..4cbf3614cc 100644 --- a/posix/getopt.c +++ b/posix/getopt.c @@ -24,19 +24,19 @@ /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. Ditto for AIX 3.2 and <stdlib.h>. */ #ifndef _NO_PROTO -#define _NO_PROTO +# define _NO_PROTO #endif #ifdef HAVE_CONFIG_H -#include <config.h> +# include <config.h> #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ -#ifndef const -#define const -#endif +# ifndef const +# define const +# endif #endif #include <stdio.h> @@ -51,10 +51,10 @@ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -#include <gnu-versions.h> -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif +# include <gnu-versions.h> +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif #endif #ifndef ELIDE_CODE @@ -65,26 +65,26 @@ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ -#include <stdlib.h> -#include <unistd.h> +# include <stdlib.h> +# include <unistd.h> #endif /* GNU C library. */ #ifdef VMS -#include <unixlib.h> -#if HAVE_STRING_H - 0 -#include <string.h> -#endif +# include <unixlib.h> +# if HAVE_STRING_H - 0 +# include <string.h> +# endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ -#ifdef HAVE_LIBINTL_H -# include <libintl.h> -# define _(msgid) gettext (msgid) -#else -# define _(msgid) (msgid) -#endif +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' @@ -194,14 +194,19 @@ static char *posixly_correct; because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ -#include <string.h> -#define my_index strchr +# include <string.h> +# define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ -char *getenv (); +#ifndef getenv +extern char *getenv (); +#endif +#ifndef strncmp +extern int strncmp (); +#endif static char * my_index (str, chr) @@ -222,11 +227,11 @@ my_index (str, chr) #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ -#if !defined __STDC__ || !__STDC__ +# if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); -#endif /* not __STDC__ */ +# endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ @@ -524,11 +529,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) #else -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') diff --git a/posix/regex.c b/posix/regex.c index b7fb962d61..e2d31a0427 100644 --- a/posix/regex.c +++ b/posix/regex.c @@ -1083,17 +1083,9 @@ static const char *re_error_msgid[] = # if defined MATCH_MAY_ALLOCATE /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ -# ifdef _LIBC -long int __re_max_failures = 4000; -# else long int re_max_failures = 4000; -# endif # else -# ifdef _LIBC -long int __re_max_failures = 2000; -# else long int re_max_failures = 2000; -# endif # endif union fail_stack_elt @@ -1116,24 +1108,11 @@ typedef struct # if defined MATCH_MAY_ALLOCATE /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ -# ifdef _LIBC -int __re_max_failures = 20000; -# else int re_max_failures = 20000; -# endif # else -# ifdef _LIBC -int __re_max_failures = 2000; -# else int re_max_failures = 2000; -# endif # endif -#ifdef _LIBC -weak_alias (__re_max_failures, re_max_failures) -# define re_max_failures __re_max_failures -#endif - union fail_stack_elt { unsigned char *pointer; diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c index ba69476e4c..81f93a1577 100644 --- a/posix/wordexp-test.c +++ b/posix/wordexp-test.c @@ -150,6 +150,7 @@ struct test_case_struct }; static int testit (struct test_case_struct *tc); +static int tests; void command_line_test (const char *words) @@ -204,17 +205,28 @@ main (int argc, char *argv[]) { struct test_case_struct ts; + printf ("Test %d (~root): ", ++tests); + fflush (stdout); + ts.retval = 0; ts.env = NULL; ts.words = "~root"; ts.flags = 0; ts.wordc = 1; ts.wordv[0] = pw->pw_dir; + ts.ifs = IFS; if (testit (&ts)) - ++fail; + { + printf ("FAILED\n"); + ++fail; + } + else + printf ("OK\n"); } + puts ("tests completed, now cleaning up"); + /* Clean up */ for (i = 0; globfile[i]; ++i) remove (globfile[i]); @@ -225,6 +237,8 @@ main (int argc, char *argv[]) chdir (cwd); rmdir (tmpdir); + printf ("tests failed: %d\n", fail); + return fail != 0; } @@ -232,7 +246,6 @@ main (int argc, char *argv[]) static int testit (struct test_case_struct *tc) { - static int test; int retval; wordexp_t we; int bzzzt = 0; @@ -248,7 +261,7 @@ testit (struct test_case_struct *tc) else unsetenv ("IFS"); - printf ("Test %d: ", ++test); + printf ("Test %d (%s): ", ++tests, tc->words); retval = wordexp (tc->words, &we, tc->flags); if (retval != tc->retval || (retval == 0 && we.we_wordc != tc->wordc)) diff --git a/signal/sighold.c b/signal/sighold.c index d2cb537912..730bcacb72 100644 --- a/signal/sighold.c +++ b/signal/sighold.c @@ -18,6 +18,8 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define __need_NULL +#include <stddef.h> #include <signal.h> int diff --git a/signal/sigrelse.c b/signal/sigrelse.c index 44e1001a06..971d60ffdf 100644 --- a/signal/sigrelse.c +++ b/signal/sigrelse.c @@ -18,6 +18,8 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define __need_NULL +#include <stddef.h> #include <signal.h> int diff --git a/stdlib/mblen.c b/stdlib/mblen.c index e43b076371..d60a1fb160 100644 --- a/stdlib/mblen.c +++ b/stdlib/mblen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -37,17 +37,23 @@ mblen (const char *s, size_t n) restartable functions. We simply say here all encodings have a state. */ if (s == NULL) - return 1; - - state.count = 0; - state.value = 0; - - result = __mbrtowc (NULL, s, n, &state); - - /* The `mbrtowc' functions tell us more than we need. Fold the -1 - and -2 result into -1. */ - if (result < 0) - result = -1; + result = 1; + else if (*s == '\0') + /* According to the ISO C 89 standard this is the expected behaviour. + Idiotic, but true. */ + result = 0; + else + { + state.count = 0; + state.value = 0; + + result = __mbrtowc (NULL, s, n, &state); + + /* The `mbrtowc' functions tell us more than we need. Fold the -1 + and -2 result into -1. */ + if (result < 0) + result = -1; + } return result; } diff --git a/stdlib/mbtowc.c b/stdlib/mbtowc.c index 61b46f882e..50e7c09834 100644 --- a/stdlib/mbtowc.c +++ b/stdlib/mbtowc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -43,14 +43,22 @@ mbtowc (wchar_t *pwc, const char *s, size_t n) restartable functions. We simply say here all encodings have a state. */ if (s == NULL) - return 1; + result = 1; + else if (*s == '\0') + { + if (pwc != NULL) + *pwc = L'\0'; + result = 0; + } + else + { + result = __mbrtowc (pwc, s, n, &__no_r_state); - result = __mbrtowc (pwc, s, n, &__no_r_state); - - /* The `mbrtowc' functions tell us more than we need. Fold the -1 - and -2 result into -1. */ - if (result < 0) - result = -1; + /* The `mbrtowc' functions tell us more than we need. Fold the -1 + and -2 result into -1. */ + if (result < 0) + result = -1; + } return result; } diff --git a/sysdeps/arm/bits/setjmp.h b/sysdeps/arm/bits/setjmp.h index 5cf9cd75c7..ea25a9ba87 100644 --- a/sysdeps/arm/bits/setjmp.h +++ b/sysdeps/arm/bits/setjmp.h @@ -1,3 +1,21 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + /* Define the machine-dependent type `jmp_buf'. ARM version. */ #ifndef _SETJMP_H diff --git a/sysdeps/arm/strlen.S b/sysdeps/arm/strlen.S new file mode 100644 index 0000000000..9acef4f935 --- /dev/null +++ b/sysdeps/arm/strlen.S @@ -0,0 +1,55 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Code contributed by Matthew Wilcox <willy@odie.barnet.ac.uk> + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <sysdep.h> + +/* size_t strlen(const char *S) + * entry: r0 -> string + * exit: r0 = len + */ + +ENTRY(strlen) + bic r1, r0, $3 @ addr of word containing first byte + ldr r2, [r1], $4 @ get the first word + ands r3, r0, $3 @ how many bytes are duff? + rsb r0, r3, $0 @ get - that number into counter. + beq Laligned @ skip into main check routine if no + @ more + orr r2, r2, $0xff000000 @ set this byte to non-zero + subs r3, r3, $1 @ any more to do? + orrgt r2, r2, $0x00ff0000 @ if so, set this byte + subs r3, r3, $1 @ more? + orrgt r2, r2, $0x0000ff00 @ then set. +Laligned: @ here, we have a word in r2. Does it + tst r2, $0x000000ff @ contain any zeroes? + tstne r2, $0x0000ff00 @ + tstne r2, $0x00ff0000 @ + tstne r2, $0xff000000 @ + addne r0, r0, $4 @ if not, the string is 4 bytes longer + ldrne r2, [r1], $4 @ and we continue to the next word + bne Laligned @ +Llastword: @ drop through to here once we find a + tst r2, $0x000000ff @ word that has a zero byte in it + addne r0, r0, $1 @ + tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it + addne r0, r0, $1 @ + tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th + addne r0, r0, $1 @ must be zero) + RETINSTR(mov,pc,lr) +END(strlen) diff --git a/sysdeps/generic/bits/socket.h b/sysdeps/generic/bits/socket.h index 5dc1e65370..01844bc143 100644 --- a/sysdeps/generic/bits/socket.h +++ b/sysdeps/generic/bits/socket.h @@ -17,6 +17,9 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H 1 + #if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H # error "Never include <bits/socket.h> directly; use <sys/socket.h> instead." #endif @@ -196,3 +199,5 @@ struct linger int l_onoff; /* Nonzero to linger on close. */ int l_linger; /* Time to linger. */ }; + +#endif /* bits/socket.h */ diff --git a/sysdeps/generic/bits/utmpx.h b/sysdeps/generic/endutxent.c index e22660f6d6..cd8d7e4122 100644 --- a/sysdeps/generic/bits/utmpx.h +++ b/sysdeps/generic/endutxent.c @@ -1,5 +1,6 @@ -/* Structures and definitions for the user accounting database. Generic/BSDish - Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -16,19 +17,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _UTMPX_H -# error "Never include <bits/utmpx.h> directly; use <utmpx.h> instead." -#endif +#include <utmp.h> +#include <utmpx.h> - -#define __UT_NAMESIZE 8 -#define __UT_LINESIZE 8 -#define __UT_HOSTSIZE 16 - -struct utmpx - { - char ut_line[__UT_LINESIZE]; - char ut_name[__UT_NAMESIZE]; - char ut_host[__UT_HOSTSIZE]; - long int ut_time; - }; +void +endutxent (void) +{ + __endutent (); +} diff --git a/sysdeps/generic/getutxent.c b/sysdeps/generic/getutxent.c new file mode 100644 index 0000000000..f6f07d5c44 --- /dev/null +++ b/sysdeps/generic/getutxent.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +getutxent (void) +{ + return (struct utmpx *) __getutent (); +} diff --git a/sysdeps/generic/getutxid.c b/sysdeps/generic/getutxid.c new file mode 100644 index 0000000000..d58f4c307d --- /dev/null +++ b/sysdeps/generic/getutxid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +getutxid (const struct utmpx *id) +{ + return (struct utmpx *) __getutid ((const struct utmp *) id); +} diff --git a/sysdeps/generic/getutxline.c b/sysdeps/generic/getutxline.c new file mode 100644 index 0000000000..4296ea615b --- /dev/null +++ b/sysdeps/generic/getutxline.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +getutxline (const struct utmpx *line) +{ + return (struct utmpx *) __getutline ((const struct utmp *) line); +} diff --git a/sysdeps/generic/longjmp.c b/sysdeps/generic/longjmp.c index f46f1601c3..1a4850f1b8 100644 --- a/sysdeps/generic/longjmp.c +++ b/sysdeps/generic/longjmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1994, 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 94, 95, 97, 98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -27,7 +27,7 @@ extern void _longjmp_unwind (jmp_buf env, int val); to the position specified in ENV, causing the setjmp call there to return VAL, or 1 if VAL is 0. */ void -longjmp (sigjmp_buf env, int val) +__libc_siglongjmp (sigjmp_buf env, int val) { /* Perform any cleanups needed by the frames being unwound. */ _longjmp_unwind (env, val); @@ -41,5 +41,7 @@ longjmp (sigjmp_buf env, int val) __longjmp (env[0].__jmpbuf, val ?: 1); } -weak_alias (longjmp, _longjmp) -weak_alias (longjmp, siglongjmp) +strong_alias (__libc_siglongjmp, __libc_longjmp) +weak_alias (__libc_siglongjmp, _longjmp) +weak_alias (__libc_siglongjmp, longjmp) +weak_alias (__libc_siglongjmp, siglongjmp) diff --git a/sysdeps/generic/pututxline.c b/sysdeps/generic/pututxline.c new file mode 100644 index 0000000000..d1246bc5a4 --- /dev/null +++ b/sysdeps/generic/pututxline.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +struct utmpx * +pututxline (const struct utmpx *utmpx) +{ + return (struct utmpx *) __pututline ((const struct utmp *) utmpx); +} diff --git a/sysdeps/generic/setjmp.c b/sysdeps/generic/setjmp.c index 8b1dfa6a83..56230aabf7 100644 --- a/sysdeps/generic/setjmp.c +++ b/sysdeps/generic/setjmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 94, 95, 96, 97, 98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,7 +22,7 @@ /* Save the current program position in ENV and return 0. */ int -__sigsetjmp (jmp_buf env, int savemask) +__libc_sigsetjmp (jmp_buf env, int savemask) { /* Save the signal mask if requested. */ __sigjmp_save (env, savemask); @@ -32,6 +32,6 @@ __sigsetjmp (jmp_buf env, int savemask) return 0; } - +weak_alias (__libc_sigsetjmp, __sigsetjmp) stub_warning (__sigsetjmp) #include <stub-tag.h> diff --git a/sysdeps/generic/setutxent.c b/sysdeps/generic/setutxent.c new file mode 100644 index 0000000000..267a1bd7d1 --- /dev/null +++ b/sysdeps/generic/setutxent.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +void +setutxent (void) +{ + return __setutent (); +} diff --git a/sysdeps/generic/strcasestr.c b/sysdeps/generic/strcasestr.c index ec8727d268..a5786fac58 100644 --- a/sysdeps/generic/strcasestr.c +++ b/sysdeps/generic/strcasestr.c @@ -1,5 +1,5 @@ /* Return the offset of one string within another. - Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -38,7 +38,8 @@ typedef unsigned chartype; -#undef strstr +#undef strcasestr +#undef __strcasestr char * __strcasestr (phaystack, pneedle) diff --git a/login/updwtmp.c b/sysdeps/generic/updwtmp.c index 9965a61fbb..d6f29b1851 100644 --- a/login/updwtmp.c +++ b/sysdeps/generic/updwtmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. @@ -17,30 +17,25 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <unistd.h> #include <utmp.h> #include "utmp-private.h" +#ifndef TRANSFORM_UTMP_FILE_NAME +# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) +#endif void -updwtmp (const char *wtmp_file, const struct utmp *utmp) +__updwtmp (const char *wtmp_file, const struct utmp *utmp) { /* See whether utmpd is running. */ if ((*__libc_utmp_daemon_functions.updwtmp) (wtmp_file, utmp) < 0) { - /* Use the normal file, but if the current file is _PATH_UTMP or - _PATH_WTMP and the corresponding extended file (with an extra - 'x' added to the pathname) exists, we use the extended file, - because the original file is in a different format. */ - if (strcmp (wtmp_file, _PATH_UTMP) == 0 - && __access (_PATH_UTMP "x", F_OK) == 0) - (*__libc_utmp_file_functions.updwtmp) (_PATH_UTMP "x", utmp); - else if (strcmp (wtmp_file, _PATH_WTMP) == 0 - && __access (_PATH_WTMP "x", F_OK) == 0) - (*__libc_utmp_file_functions.updwtmp) (_PATH_WTMP "x", utmp); - else - (*__libc_utmp_file_functions.updwtmp) (wtmp_file, utmp); + const char *file_name; + + file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file); + + (*__libc_utmp_file_functions.updwtmp) (file_name, utmp); } } - +weak_alias (__updwtmp, updwtmp) diff --git a/sysdeps/generic/updwtmpx.c b/sysdeps/generic/updwtmpx.c new file mode 100644 index 0000000000..097bf380d2 --- /dev/null +++ b/sysdeps/generic/updwtmpx.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +void +__updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx) +{ + __updwtmp (wtmpx_file, (const struct utmp *) utmpx); +} diff --git a/login/utmp_file.c b/sysdeps/generic/utmp_file.c index 9cdb88ebec..08675185ce 100644 --- a/login/utmp_file.c +++ b/sysdeps/generic/utmp_file.c @@ -61,19 +61,18 @@ struct utfuncs __libc_utmp_file_functions = }; +#ifndef TRANSFORM_UTMP_FILE_NAME +# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) +#endif + static int setutent_file (void) { if (file_fd < 0) { - const char *file_name = __libc_utmp_file_name; + const char *file_name; - if (strcmp (__libc_utmp_file_name, _PATH_UTMP) == 0 - && __access (_PATH_UTMP "x", F_OK) == 0) - file_name = _PATH_UTMP "x"; - else if (strcmp (__libc_utmp_file_name, _PATH_WTMP) == 0 - && __access (_PATH_WTMP "x", F_OK) == 0) - file_name = _PATH_WTMP "x"; + file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); file_fd = open (file_name, O_RDWR); if (file_fd == -1) @@ -81,10 +80,7 @@ setutent_file (void) /* Hhm, read-write access did not work. Try read-only. */ file_fd = open (file_name, O_RDONLY); if (file_fd == -1) - { - perror (_("while opening UTMP file")); - return 0; - } + return 0; } } diff --git a/sysdeps/generic/utmpxname.c b/sysdeps/generic/utmpxname.c new file mode 100644 index 0000000000..41c91937d0 --- /dev/null +++ b/sysdeps/generic/utmpxname.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <utmp.h> +#include <utmpx.h> + +int +utmpxname (const char *file) +{ + return __utmpname (file); +} diff --git a/sysdeps/gnu/Makefile b/sysdeps/gnu/Makefile index e491fa2be4..762f79b866 100644 --- a/sysdeps/gnu/Makefile +++ b/sysdeps/gnu/Makefile @@ -28,3 +28,10 @@ $(..)sysdeps/gnu/errlist.c: $(..)sysdeps/gnu/errlist.awk \ ifeq ($(with-cvs),yes) test ! -d CVS || cvs commit -m'Regenerated from $^' $@ endif + +ifeq ($(subdir),login) +sysdep_routines += setutxent getutxent endutxent getutxid getutxline \ + pututxline utmpxname updwtmpx + +sysdep_headers += utmpx.h bits/utmpx.h +endif diff --git a/sysdeps/gnu/bits/utmpx.h b/sysdeps/gnu/bits/utmpx.h index 4ecbb3a026..b367bfba3c 100644 --- a/sysdeps/gnu/bits/utmpx.h +++ b/sysdeps/gnu/bits/utmpx.h @@ -1,5 +1,5 @@ /* Structures and defenitions for the user accounting database. GNU version. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -24,6 +24,13 @@ #include <sys/time.h> +#ifdef __USE_GNU +# include <paths.h> +# define _PATH_UTMPX _PATH_UTMP +# define _PATH_WTMPX _PATH_WTMP +#endif + + #define __UT_LINESIZE 32 #define __UT_NAMESIZE 32 #define __UT_HOSTSIZE 256 @@ -56,10 +63,12 @@ struct utmpx }; -/* Values for the `ut_type' field of a `struct utmp'. */ +/* Values for the `ut_type' field of a `struct utmpx'. */ #define EMPTY 0 /* No valid user accounting information. */ -#define RUN_LVL 1 /* The system's runlevel. */ +#ifdef __USE_GNU +# define RUN_LVL 1 /* The system's runlevel. */ +#endif #define BOOT_TIME 2 /* Time of system boot. */ #define NEW_TIME 3 /* Time after system clock changed. */ #define OLD_TIME 4 /* Time when system clock changed. */ @@ -68,3 +77,7 @@ struct utmpx #define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ #define USER_PROCESS 7 /* Normal process. */ #define DEAD_PROCESS 8 /* Terminated process. */ + +#ifdef __USE_GNU +# define ACCOUNTING 9 /* System accounting. */ +#endif diff --git a/sysdeps/gnu/updwtmp.c b/sysdeps/gnu/updwtmp.c new file mode 100644 index 0000000000..19a77657b3 --- /dev/null +++ b/sysdeps/gnu/updwtmp.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <unistd.h> + +#define TRANSFORM_UTMP_FILE_NAME(file_name) \ + ((strcmp (file_name, _PATH_UTMP "x") == 0 \ + && __access (_PATH_UTMP "x", F_OK) != 0) ? _PATH_UTMP : \ + ((strcmp (file_name, _PATH_WTMP "x") == 0 \ + && __access (_PATH_WTMP "x", F_OK) != 0) ? _PATH_WTMP : \ + file_name)) + +#include <sysdeps/generic/updwtmp.c> diff --git a/sysdeps/gnu/utmp_file.c b/sysdeps/gnu/utmp_file.c new file mode 100644 index 0000000000..05bbcd1ce1 --- /dev/null +++ b/sysdeps/gnu/utmp_file.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <unistd.> + +#define TRANSFORM_UTMP_FILE_NAME(file_name) \ + ((strcmp (file_name, _PATH_UTMP "x") == 0 \ + && __access (_PATH_UTMP "x", F_OK) != 0) ? _PATH_UTMP : \ + ((strcmp (file_name, _PATH_WTMP "x") == 0 \ + && __access (_PATH_WTMP "x", F_OK) != 0) ? _PATH_WTMP : \ + file_name)) + +#include <sysdeps/generic/utmp_file.c> diff --git a/login/utmpx.h b/sysdeps/gnu/utmpx.h index 5873bf9310..e9f2389b75 100644 --- a/login/utmpx.h +++ b/sysdeps/gnu/utmpx.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. @@ -27,8 +27,16 @@ __BEGIN_DECLS /* Get system dependent values and data structures. */ #include <bits/utmpx.h> +#ifdef __USE_GNU +/* Compatibility names for the strings of the canonical file names. */ +# define UTMPX_FILE _PATH_UTMPX +# define UTMPX_FILENAME _PATH_UTMPX +# define WTMPX_FILE _PATH_WTMPX +# define WTMPX_FILENAME _PATH_WTMPX +#endif + /* Open user accounting database. */ -extern void *setutxent __P ((void)); +extern void setutxent __P ((void)); /* Close user accounting database. */ extern void endutxent __P ((void)); @@ -45,6 +53,15 @@ extern struct utmpx *getutxline __P ((const struct utmpx *__line)); /* Write the entry UTMPX into the user accounting database. */ extern struct utmpx *pututxline __P ((const struct utmpx *__utmpx)); +#ifdef __USE_GNU +/* Change name of the utmpx file to be examined. */ +extern int utmpxname __P ((__const char *__file)); + +/* Append entry UTMP to the wtmpx-like file WTMPX_FILE. */ +extern void updwtmpx __P ((__const char *__wtmpx_file, + __const struct utmpx *__utmpx)); +#endif + __END_DECLS #endif /* utmpx.h */ diff --git a/sysdeps/i386/bits/setjmp.h b/sysdeps/i386/bits/setjmp.h index 5cb60a8c7d..46729224fd 100644 --- a/sysdeps/i386/bits/setjmp.h +++ b/sysdeps/i386/bits/setjmp.h @@ -1,3 +1,21 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + /* Define the machine-dependent type `jmp_buf'. Intel 386 version. */ #ifndef _SETJMP_H diff --git a/sysdeps/m68k/bits/setjmp.h b/sysdeps/m68k/bits/setjmp.h index 2991232915..a302b72393 100644 --- a/sysdeps/m68k/bits/setjmp.h +++ b/sysdeps/m68k/bits/setjmp.h @@ -1,3 +1,21 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + /* Define the machine-dependent type `jmp_buf'. m68k version. */ #ifndef _SETJMP_H diff --git a/sysdeps/mach/hurd/Subdirs b/sysdeps/mach/hurd/Subdirs index 739919f4b1..16b8348437 100644 --- a/sysdeps/mach/hurd/Subdirs +++ b/sysdeps/mach/hurd/Subdirs @@ -1,2 +1 @@ hurd -login diff --git a/sysdeps/mach/hurd/bits/ioctls.h b/sysdeps/mach/hurd/bits/ioctls.h index 1145560ab9..1e063e3e66 100644 --- a/sysdeps/mach/hurd/bits/ioctls.h +++ b/sysdeps/mach/hurd/bits/ioctls.h @@ -16,7 +16,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#if !defined _HURD_IOCTL_H && !defined _SYS_IOCTLS_H +#ifndef __BITS_IOCTLS_H +#define __BITS_IOCTLS_H 1 + +#if !defined _HURD_IOCTL_H && !defined _SYS_IOCTL_H # error "Never use <bits/ioctls.h> directly; include <hurd/ioctl.h> instead." #endif @@ -345,3 +348,5 @@ enum __ioctl_datum { IOC_8, IOC_16, IOC_32, IOC_64 }; # define EXTA 14 # define EXTB 15 #endif /* USE_OLD_TTY */ + +#endif /* bits/ioctls.h */ diff --git a/sysdeps/posix/sigignore.c b/sysdeps/posix/sigignore.c index f24aca70c9..497af577f8 100644 --- a/sysdeps/posix/sigignore.c +++ b/sysdeps/posix/sigignore.c @@ -19,6 +19,8 @@ Boston, MA 02111-1307, USA. */ #include <errno.h> +#define __need_NULL +#include <stddef.h> #include <signal.h> int diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c index 4bd3bf38c8..1a6b1a4fd3 100644 --- a/sysdeps/posix/sigset.c +++ b/sysdeps/posix/sigset.c @@ -17,6 +17,8 @@ Boston, MA 02111-1307, USA. */ #include <errno.h> +#define __need_NULL +#include <stddef.h> #include <signal.h> diff --git a/sysdeps/posix/waitid.c b/sysdeps/posix/waitid.c index a36883a8d2..fa9021115f 100644 --- a/sysdeps/posix/waitid.c +++ b/sysdeps/posix/waitid.c @@ -1,5 +1,5 @@ /* Pseudo implementation of waitid. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1997. @@ -20,6 +20,8 @@ #include <errno.h> #include <signal.h> +#define __need_NULL +#include <stddef.h> #include <sys/wait.h> #include <sys/types.h> diff --git a/sysdeps/powerpc/bits/setjmp.h b/sysdeps/powerpc/bits/setjmp.h index 7bb654c0bc..65db364555 100644 --- a/sysdeps/powerpc/bits/setjmp.h +++ b/sysdeps/powerpc/bits/setjmp.h @@ -1,3 +1,21 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + /* Define the machine-dependent type `jmp_buf'. PowerPC version. */ #ifndef _SETJMP_H diff --git a/sysdeps/powerpc/elf/start.c b/sysdeps/powerpc/elf/start.c deleted file mode 100644 index d32aeee6c7..0000000000 --- a/sysdeps/powerpc/elf/start.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Startup code compliant to the ELF PowerPC ABI. - Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* This is SVR4/PPC ABI compliant, and works under Linux when - statically linked. */ - -#include <unistd.h> -#include <stdlib.h> - -/* Just a little assembler stub before gcc gets its hands on our - stack pointer... */ -asm ("\ - .section \".text\" - .align 2 - .globl _start - .type _start,@function -_start: - # save the stack pointer, in case we're statically linked under Linux - mr 8,1 - # set up an initial stack frame, and clear the LR - addi 1,1,-16 - clrrwi 1,1,4 - li 0,0 - stw 0,0(1) - mtlr 0 - # set r13 to point at the 'small data area' - lis 13,_SDA_BASE_@ha - addi 13,13,_SDA_BASE_@l - # and continue below. - b __start1 -0: - .size _start,0b-_start - # undo '.section text'. - .previous -"); - -/* Define a symbol for the first piece of initialized data. */ -int __data_start = 0; -weak_alias (__data_start, data_start) - -/* these probably should go, at least go somewhere else - (sysdeps/mach/something?). */ -void (*_mach_init_routine) (void); -void (*_thread_init_routine) (void); - -extern void __libc_init_first (int argc, char **argv, char **envp); -extern int main (int argc, char **argv, char **envp, void *auxvec); -#ifdef HAVE_INITFINI -extern void _init (void); -extern void _fini (void); -#endif - -#if 0 -/* I'd like to say this, but it causes GCC to strip the whole procedure - from the object file (this is sort of reasonable, because you've told - GCC that the procedure is unused). :-( */ -static void __start1(int argc, char **argv, char **envp, - void *auxvec, void (*exitfn) (void), - char **stack_on_entry) - __attribute__ ((unused)); - -static -#endif -void -__start1(int argc, char **argv, char **envp, - void *auxvec, void (*exitfn) (void), - char **stack_on_entry) -{ - /* the PPC SVR4 ABI says that the top thing on the stack will - be a NULL pointer, so if not we assume that we're being called - as a statically-linked program by Linux... */ - if (*stack_on_entry != NULL) - { - /* ...in which case, we have argc as the top thing on the - stack, followed by argv (NULL-terminated), envp (likewise), - and the auxilary vector. */ - argc = *(int *) stack_on_entry; - argv = stack_on_entry + 1; - envp = argv + argc + 1; - auxvec = envp; - while (*(char **) auxvec != NULL) - ++auxvec; - ++auxvec; - exitfn = NULL; - } - - if (exitfn != NULL) - atexit (exitfn); - - /* libc init routine, in case we are statically linked - (otherwise ld.so will have called it when it loaded libc, but - calling it twice doesn't hurt). */ - __libc_init_first (argc, argv, envp); - -#ifdef HAVE_INITFINI - /* ELF constructors/destructors */ - atexit (_fini); - _init (); -#endif - - /* Stuff so we can build Mach/Linux executables (like vmlinux). */ - if (_mach_init_routine != 0) - _mach_init_routine (); - if (_thread_init_routine != 0) - _thread_init_routine (); - - /* the rest of the program */ - exit (main (argc, argv, envp, auxvec)); -} diff --git a/sysdeps/sparc/sparc32/bits/setjmp.h b/sysdeps/sparc/sparc32/bits/setjmp.h index 0e61fe7805..3d39132eab 100644 --- a/sysdeps/sparc/sparc32/bits/setjmp.h +++ b/sysdeps/sparc/sparc32/bits/setjmp.h @@ -1,3 +1,21 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + /* Define the machine-dependent type `jmp_buf'. SPARC version. */ #ifndef _SETJMP_H diff --git a/sysdeps/unix/sysv/linux/i386/s_pread64.S b/sysdeps/unix/sysv/linux/i386/s_pread64.S index 7f8816b3ba..23d7d14ba5 100644 --- a/sysdeps/unix/sysv/linux/i386/s_pread64.S +++ b/sysdeps/unix/sysv/linux/i386/s_pread64.S @@ -49,7 +49,7 @@ ENTRY (__syscall_pread64) cmpl $-4095, %eax /* Check %eax for error. */ jae syscall_error /* Jump to error handler if error. */ #endif - ret /* Return to caller. */ L(pseudo_end): + ret /* Return to caller. */ PSEUDO_END (__syscall_pread64) diff --git a/sysdeps/unix/sysv/linux/paths.h b/sysdeps/unix/sysv/linux/paths.h index 53c4fc5dcb..cb5b57122c 100644 --- a/sysdeps/unix/sysv/linux/paths.h +++ b/sysdeps/unix/sysv/linux/paths.h @@ -64,7 +64,6 @@ #define _PATH_TTY "/dev/tty" #define _PATH_UNIX "/vmlinux" #define _PATH_UTMP "/var/run/utmp" -#define _PATH_UTMP_DB "/var/run/utmp.db" #define _PATH_VI "/usr/bin/vi" #define _PATH_WTMP "/var/log/wtmp" diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c index fa946cf774..9e31ed4096 100644 --- a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c @@ -30,7 +30,7 @@ for (_tmp = (envp); *_tmp; ++_tmp) \ continue; \ /* The following '++' is important! */ \ - (auxp) = ++_tmp; \ + ++_tmp; \ if (*_tmp == 0) \ { \ size_t _test = (size_t)_tmp; \ @@ -42,8 +42,9 @@ vector will have to be laid out to allow for this \ test :-(. */ \ if (((ElfW(auxv_t) *)_test)->a_type <= AT_PHDR) \ - (auxp) = (ElfW(auxv_t) *) _tmp; \ + _tmp = (char **)_test; \ } \ + (auxp) = (ElfW(auxv_t) *) _tmp; \ } while (0) diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.h b/sysdeps/unix/sysv/linux/powerpc/syscall.h deleted file mode 100644 index c6bac3de5b..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/syscall.h +++ /dev/null @@ -1,357 +0,0 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _SYSCALL_H -#define _SYSCALL_H 1 - -/* normally, we'd get syscalls from asm/unistd.h under Linux, but this - is very broken under MkLinux/PPC, so we list them right here directly. */ - -#define __NR_setup 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_chown 16 -#define __NR_break 17 -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_stty 31 -#define __NR_gtty 32 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_prof 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_phys 52 -#define __NR_lock 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 -#define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_profil 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86 113 -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_modify_ldt 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 - -#ifndef _LIBC -#define SYS_setup 0 -#define SYS_exit 1 -#define SYS_fork 2 -#define SYS_read 3 -#define SYS_write 4 -#define SYS_open 5 -#define SYS_close 6 -#define SYS_waitpid 7 -#define SYS_creat 8 -#define SYS_link 9 -#define SYS_unlink 10 -#define SYS_execve 11 -#define SYS_chdir 12 -#define SYS_time 13 -#define SYS_mknod 14 -#define SYS_chmod 15 -#define SYS_chown 16 -#define SYS_break 17 -#define SYS_oldstat 18 -#define SYS_lseek 19 -#define SYS_getpid 20 -#define SYS_mount 21 -#define SYS_umount 22 -#define SYS_setuid 23 -#define SYS_getuid 24 -#define SYS_stime 25 -#define SYS_ptrace 26 -#define SYS_alarm 27 -#define SYS_oldfstat 28 -#define SYS_pause 29 -#define SYS_utime 30 -#define SYS_stty 31 -#define SYS_gtty 32 -#define SYS_access 33 -#define SYS_nice 34 -#define SYS_ftime 35 -#define SYS_sync 36 -#define SYS_kill 37 -#define SYS_rename 38 -#define SYS_mkdir 39 -#define SYS_rmdir 40 -#define SYS_dup 41 -#define SYS_pipe 42 -#define SYS_times 43 -#define SYS_prof 44 -#define SYS_brk 45 -#define SYS_setgid 46 -#define SYS_getgid 47 -#define SYS_signal 48 -#define SYS_geteuid 49 -#define SYS_getegid 50 -#define SYS_acct 51 -#define SYS_phys 52 -#define SYS_lock 53 -#define SYS_ioctl 54 -#define SYS_fcntl 55 -#define SYS_mpx 56 -#define SYS_setpgid 57 -#define SYS_ulimit 58 -#define SYS_oldolduname 59 -#define SYS_umask 60 -#define SYS_chroot 61 -#define SYS_ustat 62 -#define SYS_dup2 63 -#define SYS_getppid 64 -#define SYS_getpgrp 65 -#define SYS_setsid 66 -#define SYS_sigaction 67 -#define SYS_sgetmask 68 -#define SYS_ssetmask 69 -#define SYS_setreuid 70 -#define SYS_setregid 71 -#define SYS_sigsuspend 72 -#define SYS_sigpending 73 -#define SYS_sethostname 74 -#define SYS_setrlimit 75 -#define SYS_getrlimit 76 -#define SYS_getrusage 77 -#define SYS_gettimeofday 78 -#define SYS_settimeofday 79 -#define SYS_getgroups 80 -#define SYS_setgroups 81 -#define SYS_select 82 -#define SYS_symlink 83 -#define SYS_oldlstat 84 -#define SYS_readlink 85 -#define SYS_uselib 86 -#define SYS_swapon 87 -#define SYS_reboot 88 -#define SYS_readdir 89 -#define SYS_mmap 90 -#define SYS_munmap 91 -#define SYS_truncate 92 -#define SYS_ftruncate 93 -#define SYS_fchmod 94 -#define SYS_fchown 95 -#define SYS_getpriority 96 -#define SYS_setpriority 97 -#define SYS_profil 98 -#define SYS_statfs 99 -#define SYS_fstatfs 100 -#define SYS_ioperm 101 -#define SYS_socketcall 102 -#define SYS_syslog 103 -#define SYS_setitimer 104 -#define SYS_getitimer 105 -#define SYS_stat 106 -#define SYS_lstat 107 -#define SYS_fstat 108 -#define SYS_olduname 109 -#define SYS_iopl 110 -#define SYS_vhangup 111 -#define SYS_idle 112 -#define SYS_vm86 113 -#define SYS_wait4 114 -#define SYS_swapoff 115 -#define SYS_sysinfo 116 -#define SYS_ipc 117 -#define SYS_fsync 118 -#define SYS_sigreturn 119 -#define SYS_clone 120 -#define SYS_setdomainname 121 -#define SYS_uname 122 -#define SYS_modify_ldt 123 -#define SYS_adjtimex 124 -#define SYS_mprotect 125 -#define SYS_sigprocmask 126 -#define SYS_create_module 127 -#define SYS_init_module 128 -#define SYS_delete_module 129 -#define SYS_get_kernel_syms 130 -#define SYS_quotactl 131 -#define SYS_getpgid 132 -#define SYS_fchdir 133 -#define SYS_bdflush 134 -#define SYS_sysfs 135 -#define SYS_personality 136 -#define SYS_afs_syscall 137 /* Syscall for Andrew File System */ -#define SYS_setfsuid 138 -#define SYS_setfsgid 139 -#define SYS__llseek 140 -#define SYS_getdents 141 -#define SYS__newselect 142 -#define SYS_flock 143 -#define SYS_msync 144 -#define SYS_readv 145 -#define SYS_writev 146 -#define SYS_getsid 147 -#define SYS_fdatasync 148 -#define SYS__sysctl 149 -#define SYS_mlock 150 -#define SYS_munlock 151 -#define SYS_mlockall 152 -#define SYS_munlockall 153 -#define SYS_sched_setparam 154 -#define SYS_sched_getparam 155 -#define SYS_sched_setscheduler 156 -#define SYS_sched_getscheduler 157 -#define SYS_sched_yield 158 -#define SYS_sched_get_priority_max 159 -#define SYS_sched_get_priority_min 160 -#define SYS_sched_rr_get_interval 161 -#define SYS_nanosleep 162 -#define SYS_mremap 163 -#endif - -#endif diff --git a/sysdeps/unix/sysv/linux/rt_sigsuspend.c b/sysdeps/unix/sysv/linux/rt_sigsuspend.c index dc32dcc067..f6f4987cd1 100644 --- a/sysdeps/unix/sysv/linux/rt_sigsuspend.c +++ b/sysdeps/unix/sysv/linux/rt_sigsuspend.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,6 +18,8 @@ #include <errno.h> #include <signal.h> +#define __need_NULL +#include <stddef.h> int __syscall_rt_sigsuspend (const sigset_t *set, size_t setsize) diff --git a/sysdeps/unix/sysv/linux/rt_sigtimedwait.c b/sysdeps/unix/sysv/linux/rt_sigtimedwait.c index 4513026f44..3bf9834fa7 100644 --- a/sysdeps/unix/sysv/linux/rt_sigtimedwait.c +++ b/sysdeps/unix/sysv/linux/rt_sigtimedwait.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,6 +18,8 @@ #include <errno.h> #include <signal.h> +#define __need_NULL +#include <stddef.h> int __syscall_rt_sigtimedwait (const sigset_t *set, siginfo_t *info, diff --git a/sysdeps/unix/sysv/linux/sigwaitinfo.c b/sysdeps/unix/sysv/linux/sigwaitinfo.c index 5f41ba054b..da4624e53e 100644 --- a/sysdeps/unix/sysv/linux/sigwaitinfo.c +++ b/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,6 +17,8 @@ Boston, MA 02111-1307, USA. */ #include <signal.h> +#define __need_NULL +#include <stddef.h> extern int __syscall_rt_sigtimedwait (const sigset_t *, siginfo_t *, const struct timespec *, size_t); diff --git a/sysdeps/unix/sysv/linux/updwtmp.c b/sysdeps/unix/sysv/linux/updwtmp.c new file mode 100644 index 0000000000..e2156a123b --- /dev/null +++ b/sysdeps/unix/sysv/linux/updwtmp.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <unistd.h> + +#define TRANSFORM_UTMP_FILE_NAME(file_name) \ + ((strcmp (file_name, _PATH_UTMP) == 0 \ + && __access (_PATH_UTMP "x", F_OK) == 0) ? (_PATH_UTMP "x") : \ + ((strcmp (file_name, _PATH_WTMP) == 0 \ + && __access ( _PATH_WTMP "x", F_OK) == 0) ? (_PATH_WTMP "x") : \ + ((strcmp (file_name, _PATH_UTMP "x") == 0 \ + && __access (_PATH_UTMP "x", F_OK) != 0) ? _PATH_UTMP : \ + ((strcmp (file_name, _PATH_WTMP "x") == 0 \ + && __access (_PATH_WTMP "x", F_OK) != 0) ? _PATH_WTMP : \ + file_name)))) + +#include <sysdeps/generic/updwtmp.c> diff --git a/sysdeps/unix/sysv/linux/utmp_file.c b/sysdeps/unix/sysv/linux/utmp_file.c new file mode 100644 index 0000000000..5775270123 --- /dev/null +++ b/sysdeps/unix/sysv/linux/utmp_file.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <unistd.h> + +#define TRANSFORM_UTMP_FILE_NAME(file_name) \ + ((strcmp (file_name, _PATH_UTMP) == 0 \ + && __access (_PATH_UTMP "x", F_OK) == 0) ? (_PATH_UTMP "x") : \ + ((strcmp (file_name, _PATH_WTMP) == 0 \ + && __access ( _PATH_WTMP "x", F_OK) == 0) ? (_PATH_WTMP "x") : \ + ((strcmp (file_name, _PATH_UTMP "x") == 0 \ + && __access (_PATH_UTMP "x", F_OK) != 0) ? _PATH_UTMP : \ + ((strcmp (file_name, _PATH_WTMP "x") == 0 \ + && __access (_PATH_WTMP "x", F_OK) != 0) ? _PATH_WTMP : \ + file_name)))) + +#include <sysdeps/generic/utmp_file.c> diff --git a/wcsmbs/btowc.c b/wcsmbs/btowc.c index 7efe62e5f1..b40a98f65b 100644 --- a/wcsmbs/btowc.c +++ b/wcsmbs/btowc.c @@ -31,7 +31,7 @@ __btowc (c) char buf[sizeof (wchar_t)]; struct gconv_step_data data; char inbuf[1]; - size_t inbytes; + char *inptr = inbuf; size_t converted; int status; @@ -42,8 +42,7 @@ __btowc (c) /* Tell where we want the result. */ data.outbuf = (char *) buf; - data.outbufavail = 0; - data.outbufsize = sizeof (wchar_t); + data.outbufend = data.outbuf + sizeof (wchar_t); data.is_last = 1; data.statep = &data.__state; @@ -55,10 +54,9 @@ __btowc (c) /* Create the input string. */ inbuf[0] = c; - inbytes = 1; status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, - &data, inbuf, &inbytes, + &data, &inptr, inptr + 1, &converted, 0); /* The conversion failed. */ if (status != GCONV_OK && status != GCONV_FULL_OUTPUT diff --git a/wcsmbs/mbrtowc.c b/wcsmbs/mbrtowc.c index 14ca0b0975..1dcaf968ea 100644 --- a/wcsmbs/mbrtowc.c +++ b/wcsmbs/mbrtowc.c @@ -36,14 +36,15 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { wchar_t buf[1]; struct gconv_step_data data; - size_t inbytes; int status; size_t result; + size_t dummy; + const char *inbuf; + char *outbuf = (char *) (pwc ?: buf); /* Tell where we want the result. */ - data.outbuf = (char *) (pwc ?: buf); - data.outbufavail = 0; - data.outbufsize = sizeof (wchar_t); + data.outbuf = outbuf; + data.outbufend = outbuf + sizeof (wchar_t); data.is_last = 1; data.statep = ps ?: &state; @@ -60,9 +61,10 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) update_conversion_ptrs (); /* Do a normal conversion. */ - inbytes = n; + inbuf = s; status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, - &data, s, &inbytes, NULL, 0); + &data, &inbuf, inbuf + n, + &dummy, 0); /* There must not be any problems with the conversion but illegal input characters. The output buffer must be large enough, otherwise the @@ -76,14 +78,14 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) if (status == GCONV_OK || status == GCONV_EMPTY_INPUT || status == GCONV_FULL_OUTPUT) { - if (data.outbufavail > 0 && *(wchar_t *)data.outbuf == L'\0') + if (data.outbuf != outbuf && *(wchar_t *)data.outbuf == L'\0') { /* The converted character is the NUL character. */ assert (__mbsinit (data.statep)); result = 0; } else - result = n - inbytes; + result = inbuf - s; } else { diff --git a/wcsmbs/mbsnrtowcs.c b/wcsmbs/mbsnrtowcs.c index d408b39430..46a718b3f5 100644 --- a/wcsmbs/mbsnrtowcs.c +++ b/wcsmbs/mbsnrtowcs.c @@ -44,7 +44,7 @@ __mbsnrtowcs (dst, src, nmc, len, ps) size_t len; mbstate_t *ps; { - size_t inbytes_in; + const char *srcend; struct gconv_step_data data; size_t result = 0; int status; @@ -55,7 +55,7 @@ __mbsnrtowcs (dst, src, nmc, len, ps) if (nmc == 0) return 0; - inbytes_in = __strnlen (*src, nmc - 1) + 1; + srcend = *src + __strnlen (*src, nmc - 1) + 1; /* Make sure we use the correct function. */ update_conversion_ptrs (); @@ -64,21 +64,15 @@ __mbsnrtowcs (dst, src, nmc, len, ps) if (dst == NULL) { wchar_t buf[64]; /* Just an arbitrary size. */ - size_t inbytes = inbytes_in; const char *inbuf = *src; size_t written; data.outbuf = (char *) buf; - data.outbufsize = sizeof (buf); + data.outbufend = data.outbuf + sizeof (buf); do { - inbuf += inbytes_in - inbytes; - inbytes_in = inbytes; - data.outbufavail = 0; - written = 0; - status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, - &data, inbuf, &inbytes, + &data, &inbuf, srcend, &written, 0); result += written; } @@ -94,14 +88,11 @@ __mbsnrtowcs (dst, src, nmc, len, ps) /* This code is based on the safe assumption that all internal multi-byte encodings use the NUL byte only to mark the end of the string. */ - size_t inbytes = inbytes_in; - data.outbuf = (char *) dst; - data.outbufsize = len * sizeof (wchar_t); - data.outbufavail = 0; + data.outbufend = data.outbuf + len * sizeof (wchar_t); status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, - &data, *src, &inbytes, + &data, src, srcend, &result, 0); /* We have to determine whether the last character converted @@ -114,8 +105,6 @@ __mbsnrtowcs (dst, src, nmc, len, ps) *src = NULL; --result; } - else - *src += inbytes_in - inbytes; } /* There must not be any problems with the conversion but illegal input diff --git a/wcsmbs/mbsrtowcs.c b/wcsmbs/mbsrtowcs.c index 8f9efb3285..9172fd9ede 100644 --- a/wcsmbs/mbsrtowcs.c +++ b/wcsmbs/mbsrtowcs.c @@ -19,6 +19,7 @@ #include <errno.h> #include <gconv.h> +#include <stdlib.h> #include <string.h> #include <wchar.h> #include <wcsmbsload.h> @@ -55,22 +56,16 @@ __mbsrtowcs (dst, src, len, ps) if (dst == NULL) { wchar_t buf[64]; /* Just an arbitrary size. */ - size_t inbytes_in = strlen (*src) + 1; - size_t inbytes = inbytes_in; + const char *srcend = *src + strlen (*src) + 1; const char *inbuf = *src; size_t written; data.outbuf = (char *) buf; - data.outbufsize = sizeof (buf); + data.outbufend = data.outbuf + sizeof (buf); do { - inbuf += inbytes_in - inbytes; - inbytes_in = inbytes; - data.outbufavail = 0; - written = 0; - status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, - &data, inbuf, &inbytes, + &data, &inbuf, srcend, &written, 0); result += written; } @@ -86,15 +81,13 @@ __mbsrtowcs (dst, src, len, ps) /* This code is based on the safe assumption that all internal multi-byte encodings use the NUL byte only to mark the end of the string. */ - size_t inbytes_in = __strnlen (*src, len * MB_CUR_MAX) + 1; - size_t inbytes = inbytes_in; + const char *srcend = *src + __strnlen (*src, len * MB_CUR_MAX) + 1; data.outbuf = (char *) dst; - data.outbufsize = len * sizeof (wchar_t); - data.outbufavail = 0; + data.outbufend = data.outbuf + len * sizeof (wchar_t); status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, - &data, *src, &inbytes, + &data, src, srcend, &result, 0); /* We have to determine whether the last character converted @@ -107,8 +100,6 @@ __mbsrtowcs (dst, src, len, ps) *src = NULL; --result; } - else - *src += inbytes_in - inbytes; } /* There must not be any problems with the conversion but illegal input diff --git a/wcsmbs/wcrtomb.c b/wcsmbs/wcrtomb.c index dcc2ef67cd..6fd33e06b3 100644 --- a/wcsmbs/wcrtomb.c +++ b/wcsmbs/wcrtomb.c @@ -40,11 +40,11 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) struct gconv_step_data data; int status; size_t result; + size_t dummy; /* Tell where we want the result. */ data.outbuf = s; - data.outbufavail = 0; - data.outbufsize = MB_CUR_MAX; + data.outbufend = s + MB_CUR_MAX; data.is_last = 1; data.statep = ps ?: &state; @@ -64,23 +64,21 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) by a NUL byte. */ if (wc == L'\0') { - size_t inbytes = 0; - status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, - &data, NULL, &inbytes, - NULL, 1); + &data, NULL, NULL, &dummy, 1); if (status == GCONV_OK || status == GCONV_EMPTY_INPUT) - data.outbuf[data.outbufavail++] = '\0'; + *data.outbuf++ = '\0'; } else { /* Do a normal conversion. */ - size_t inbytes = sizeof (wchar_t); + const char *inbuf = (const char *) &wc; status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, - &data, (char *) &wc, &inbytes, - NULL, 0); + &data, &inbuf, + inbuf + sizeof (wchar_t), + &dummy, 0); } /* There must not be any problems with the conversion but illegal input @@ -94,7 +92,7 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) if (status == GCONV_OK || status == GCONV_EMPTY_INPUT || status == GCONV_FULL_OUTPUT) - result = data.outbufavail; + result = data.outbuf - s; else { result = (size_t) -1; diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c index c7e5651fe6..f4babc4eb3 100644 --- a/wcsmbs/wcsmbsload.c +++ b/wcsmbs/wcsmbsload.c @@ -37,8 +37,8 @@ static struct gconv_step to_wc = shlib_handle: NULL, modname: NULL, counter: INT_MAX, - from_name: "ANSI_X3.4-1968", - to_name: "#INTERNAL#", + from_name: "ANSI_X3.4-1968//", + to_name: "INTERNAL", fct: __gconv_transform_ascii_internal, init_fct: NULL, end_fct: NULL, @@ -50,8 +50,8 @@ static struct gconv_step to_mb = shlib_handle: NULL, modname: NULL, counter: INT_MAX, - from_name: "#INTERNAL#", - to_name: "ANSI_X3.4-1968", + from_name: "INTERNAL", + to_name: "ANSI_X3.4-1968//", fct: __gconv_transform_internal_ascii, init_fct: NULL, end_fct: NULL, @@ -113,8 +113,8 @@ __wcsmbs_load_conv (const struct locale_data *new_category) /* Get name of charset of the locale. */ charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string; - __wcsmbs_gconv_fcts.tomb = getfct (charset_name, "#INTERNAL#"); - __wcsmbs_gconv_fcts.towc = getfct ("#INTERNAL#", charset_name); + __wcsmbs_gconv_fcts.tomb = getfct (charset_name, "INTERNAL"); + __wcsmbs_gconv_fcts.towc = getfct ("INTERNAL", charset_name); /* If any of the conversion functions is not available we don't use any since this would mean we cannot convert back and diff --git a/wcsmbs/wcsnrtombs.c b/wcsmbs/wcsnrtombs.c index 0daf0e3077..4b6232a182 100644 --- a/wcsmbs/wcsnrtombs.c +++ b/wcsmbs/wcsnrtombs.c @@ -44,7 +44,7 @@ __wcsnrtombs (dst, src, nwc, len, ps) mbstate_t *ps; { struct gconv_step_data data; - size_t inbytes_in; + const wchar_t *srcend; int status; size_t result; @@ -54,7 +54,7 @@ __wcsnrtombs (dst, src, nwc, len, ps) if (nwc == 0) return 0; - inbytes_in = (__wcsnlen (*src, nwc - 1) + 1) * sizeof (wchar_t); + srcend = *src + __wcsnlen (*src, nwc - 1) + 1; /* Make sure we use the correct function. */ update_conversion_ptrs (); @@ -63,30 +63,25 @@ __wcsnrtombs (dst, src, nwc, len, ps) if (dst == NULL) { char buf[256]; /* Just an arbitrary value. */ - size_t inbytes = inbytes_in; const wchar_t *inbuf = *src; size_t written; data.outbuf = buf; - data.outbufsize = sizeof (buf); + data.outbufend = buf + sizeof (buf); do { - inbuf += (inbytes_in - inbytes) / sizeof (wchar_t); - inbytes_in = inbytes; - data.outbufavail = 0; - written = 0; - status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, &data, - (const char *) inbuf, - &inbytes, &written, 0); + (const char **) &inbuf, + (const char *) srcend, + &written, 0); result += written; } while (status == GCONV_FULL_OUTPUT); if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT) - && buf[data.outbufavail - 1] == '\0') + && data.outbuf[-1] == '\0') /* Don't count the NUL character in. */ --result; } @@ -95,28 +90,24 @@ __wcsnrtombs (dst, src, nwc, len, ps) /* This code is based on the safe assumption that all internal multi-byte encodings use the NUL byte only to mark the end of the string. */ - size_t inbytes = inbytes_in; - data.outbuf = dst; - data.outbufavail = 0; - data.outbufsize = len; + data.outbufend = dst + len; status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, - &data, (const char *) *src, - &inbytes, &result, 0); + &data, (const char **) src, + (const char *) srcend, + &result, 0); /* We have to determine whether the last character converted is the NUL character. */ if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT) - && dst[data.outbufavail - 1] == '\0') + && data.outbuf[-1] == '\0') { - assert (data.outbufavail > 0); + assert (data.outbuf != dst); assert (__mbsinit (data.statep)); *src = NULL; --result; } - else - *src += result; } /* There must not be any problems with the conversion but illegal input diff --git a/wcsmbs/wcsrtombs.c b/wcsmbs/wcsrtombs.c index 7b59fc725a..428ef3d4dd 100644 --- a/wcsmbs/wcsrtombs.c +++ b/wcsmbs/wcsrtombs.c @@ -55,31 +55,26 @@ __wcsrtombs (dst, src, len, ps) if (dst == NULL) { char buf[256]; /* Just an arbitrary value. */ - size_t inbytes_in = (__wcslen (*src) + 1) * sizeof (wchar_t); - size_t inbytes = inbytes_in; + const wchar_t *srcend = *src + __wcslen (*src) + 1; const wchar_t *inbuf = *src; size_t written; data.outbuf = buf; - data.outbufsize = sizeof (buf); + data.outbufend = buf + sizeof (buf); do { - inbuf += (inbytes_in - inbytes) / sizeof (wchar_t); - inbytes_in = inbytes; - data.outbufavail = 0; - written = 0; - status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, &data, - (const char *) inbuf, - &inbytes, &written, 0); + (const char **) &inbuf, + (const char *) srcend, + &written, 0); result += written; } while (status == GCONV_FULL_OUTPUT); if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT) - && buf[data.outbufavail - 1] == '\0') + && data.outbuf[-1] == '\0') /* Don't count the NUL character in. */ --result; } @@ -88,31 +83,27 @@ __wcsrtombs (dst, src, len, ps) /* This code is based on the safe assumption that all internal multi-byte encodings use the NUL byte only to mark the end of the string. */ - size_t inbytes_in = ((__wcsnlen (*src, len * MB_CUR_MAX) + 1) - * sizeof (wchar_t)); - size_t inbytes = inbytes_in; + const wchar_t *srcend = *src + __wcsnlen (*src, len * MB_CUR_MAX) + 1; data.outbuf = dst; - data.outbufavail = 0; - data.outbufsize = len; + data.outbufend = dst + len; status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, - &data, (const char *) *src, - &inbytes, &result, 0); + &data, (const char **) src, + (const char *) srcend, + &result, 0); /* We have to determine whether the last character converted is the NUL character. */ if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT || status == GCONV_FULL_OUTPUT) - && dst[data.outbufavail - 1] == '\0') + && data.outbuf[-1] == '\0') { - assert (data.outbufavail > 0); + assert (data.outbuf != dst); assert (__mbsinit (data.statep)); *src = NULL; --result; } - else - *src += result; } /* There must not be any problems with the conversion but illegal input diff --git a/wcsmbs/wctob.c b/wcsmbs/wctob.c index e70b4e7fe6..b06d170388 100644 --- a/wcsmbs/wctob.c +++ b/wcsmbs/wctob.c @@ -31,14 +31,13 @@ wctob (c) char buf[MB_LEN_MAX]; struct gconv_step_data data; wchar_t inbuf[1]; - size_t inbytes; + wchar_t *inptr = inbuf; size_t converted; int status; /* Tell where we want the result. */ - data.outbuf = (char *) buf; - data.outbufavail = 0; - data.outbufsize = MB_LEN_MAX; + data.outbuf = buf; + data.outbufend = buf + MB_LEN_MAX; data.is_last = 1; data.statep = &data.__state; @@ -50,15 +49,15 @@ wctob (c) /* Create the input string. */ inbuf[0] = c; - inbytes = sizeof (wchar_t); status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, &data, - (const char *) inbuf, &inbytes, + (const char **) &inptr, + (const char *) &inbuf[1], &converted, 0); /* The conversion failed or the output is too long. */ if ((status != GCONV_OK && status != GCONV_FULL_OUTPUT && status != GCONV_EMPTY_INPUT) - || data.outbufavail != 1) + || data.outbuf != buf + 1) return EOF; return buf[0]; |