diff --git a/lib/libc/iconv/Makefile.inc b/lib/libc/iconv/Makefile.inc index 0e83902..ea0b502 100644 --- a/lib/libc/iconv/Makefile.inc +++ b/lib/libc/iconv/Makefile.inc @@ -2,6 +2,8 @@ # iconv sources .PATH: ${.CURDIR}/iconv +.PATH: ${.CURDIR}/../libc_nonshared +.include "${.CURDIR}/../libc_nonshared/Makefile.inc1" MAN+= iconv.3 iconvctl.3 iconv_canonicalize.3 iconvlist.3 __iconv_get_list.3 MLINKS+= iconv.3 iconv_open.3 \ @@ -14,5 +16,6 @@ SRCS+= citrus_bcs.c citrus_bcs_strtol.c citrus_bcs_strtoul.c \ citrus_esdb.c citrus_hash.c citrus_iconv.c citrus_lookup.c \ citrus_lookup_factory.c citrus_mapper.c citrus_memstream.c \ citrus_mmap.c citrus_module.c citrus_none.c citrus_pivot_factory.c \ - citrus_prop.c citrus_stdenc.c iconv.c iconv_compat.c + citrus_prop.c citrus_stdenc.c bsd_iconv.c iconv_compat.c +STATICOBJS+=${LIBC_NONSHARED_SRCS:S/.c$/.o/} SYM_MAPS+= ${.CURDIR}/iconv/Symbol.map diff --git a/lib/libc/iconv/bsd_iconv.c b/lib/libc/iconv/bsd_iconv.c new file mode 100644 index 0000000..555efd8 --- /dev/null +++ b/lib/libc/iconv/bsd_iconv.c @@ -0,0 +1,312 @@ +/* $FreeBSD$ */ +/* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */ + +/*- + * Copyright (c) 2003 Citrus Project, + * Copyright (c) 2009, 2010 Gabor Kovesdan , + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_esdb.h" +#include "citrus_hash.h" +#include "citrus_iconv.h" + +#include "iconv-internal.h" + +#define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1) + +static iconv_t +__bsd___iconv_open(const char *out, const char *in, struct _citrus_iconv *handle) +{ + const char *out_slashes; + char *out_noslashes; + int ret; + + /* + * Remove anything following a //, as these are options (like + * //ignore, //translate, etc) and we just don't handle them. + * This is for compatibility with software that uses these + * blindly. + */ + out_slashes = strstr(out, "//"); + if (out_slashes != NULL) { + out_noslashes = strndup(out, out_slashes - out); + if (out_noslashes == NULL) { + errno = ENOMEM; + return ((iconv_t)-1); + } + ret = _citrus_iconv_open(&handle, in, out_noslashes); + free(out_noslashes); + } else { + ret = _citrus_iconv_open(&handle, in, out); + } + + if (ret) { + errno = ret == ENOENT ? EINVAL : ret; + return ((iconv_t)-1); + } + + handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE"); + handle->cv_shared->ci_hooks = NULL; + + return ((iconv_t)(void *)handle); +} + +iconv_t +__bsd_iconv_open(const char *out, const char *in) +{ + + return (__bsd___iconv_open(out, in, NULL)); +} + +int +__bsd_iconv_open_into(const char *out, const char *in, iconv_allocation_t *ptr) +{ + struct _citrus_iconv *handle; + + handle = (struct _citrus_iconv *)ptr; + return ((__bsd___iconv_open(out, in, handle) == (iconv_t)-1) ? -1 : 0); +} + +int +__bsd_iconv_close(iconv_t handle) +{ + + if (ISBADF(handle)) { + errno = EBADF; + return (-1); + } + + _citrus_iconv_close((struct _citrus_iconv *)(void *)handle); + + return (0); +} + +size_t +__bsd_iconv(iconv_t handle, const char **in, size_t *szin, char **out, size_t *szout) +{ + size_t ret; + int err; + + if (ISBADF(handle)) { + errno = EBADF; + return ((size_t)-1); + } + + err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle, + in, szin, out, szout, 0, &ret); + if (err) { + errno = err; + ret = (size_t)-1; + } + + return (ret); +} + +size_t +__bsd___iconv(iconv_t handle, const char **in, size_t *szin, char **out, + size_t *szout, uint32_t flags, size_t *invalids) +{ + size_t ret; + int err; + + if (ISBADF(handle)) { + errno = EBADF; + return ((size_t)-1); + } + + err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle, + in, szin, out, szout, flags, &ret); + if (invalids) + *invalids = ret; + if (err) { + errno = err; + ret = (size_t)-1; + } + + return (ret); +} + +int +__bsd___iconv_get_list(char ***rlist, size_t *rsz, bool sorted) +{ + int ret; + + ret = _citrus_esdb_get_list(rlist, rsz, sorted); + if (ret) { + errno = ret; + return (-1); + } + + return (0); +} + +void +__bsd___iconv_free_list(char **list, size_t sz) +{ + + _citrus_esdb_free_list(list, sz); +} + +/* + * GNU-compatibile non-standard interfaces. + */ +static int +qsort_helper(const void *first, const void *second) +{ + const char * const *s1; + const char * const *s2; + + s1 = first; + s2 = second; + return (strcmp(*s1, *s2)); +} + +void +__bsd_iconvlist(int (*do_one) (unsigned int, const char * const *, + void *), void *data) +{ + char **list, **names; + const char * const *np; + char *curitem, *curkey, *slashpos; + size_t sz; + unsigned int i, j; + + i = 0; + + if (__bsd___iconv_get_list(&list, &sz, true)) + list = NULL; + qsort((void *)list, sz, sizeof(char *), qsort_helper); + while (i < sz) { + j = 0; + slashpos = strchr(list[i], '/'); + curkey = (char *)malloc(slashpos - list[i] + 2); + names = (char **)malloc(sz * sizeof(char *)); + if ((curkey == NULL) || (names == NULL)) { + __bsd___iconv_free_list(list, sz); + return; + } + strlcpy(curkey, list[i], slashpos - list[i] + 1); + names[j++] = strdup(curkey); + for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) { + slashpos = strchr(list[i], '/'); + curitem = (char *)malloc(strlen(slashpos) + 1); + if (curitem == NULL) { + __bsd___iconv_free_list(list, sz); + return; + } + strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1); + if (strcmp(curkey, curitem) == 0) { + continue; + } + names[j++] = strdup(curitem); + } + np = (const char * const *)names; + do_one(j, np, data); + free(names); + } + + __bsd___iconv_free_list(list, sz); +} + +__inline const char * +__bsd_iconv_canonicalize(const char *name) +{ + + return (_citrus_iconv_canonicalize(name)); +} + +int +__bsd_iconvctl(iconv_t cd, int request, void *argument) +{ + struct _citrus_iconv *cv; + struct iconv_hooks *hooks; + const char *convname; + char src[PATH_MAX], *dst; + int *i; + + cv = (struct _citrus_iconv *)(void *)cd; + hooks = (struct iconv_hooks *)argument; + i = (int *)argument; + + if (ISBADF(cd)) { + errno = EBADF; + return (-1); + } + + switch (request) { + case ICONV_TRIVIALP: + convname = cv->cv_shared->ci_convname; + dst = strchr(convname, '/'); + + strlcpy(src, convname, dst - convname + 1); + dst++; + if ((convname == NULL) || (src == NULL) || (dst == NULL)) + return (-1); + *i = strcmp(src, dst) == 0 ? 1 : 0; + return (0); + case ICONV_GET_TRANSLITERATE: + *i = 1; + return (0); + case ICONV_SET_TRANSLITERATE: + return ((*i == 1) ? 0 : -1); + case ICONV_GET_DISCARD_ILSEQ: + *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0; + return (0); + case ICONV_SET_DISCARD_ILSEQ: + cv->cv_shared->ci_discard_ilseq = *i; + return (0); + case ICONV_SET_HOOKS: + cv->cv_shared->ci_hooks = hooks; + return (0); + case ICONV_SET_FALLBACKS: + errno = EOPNOTSUPP; + return (-1); + default: + errno = EINVAL; + return (-1); + } +} + +void +__bsd_iconv_set_relocation_prefix(const char *orig_prefix __unused, + const char *curr_prefix __unused) +{ + +} diff --git a/lib/libc/iconv/iconv.c b/lib/libc/iconv/iconv.c deleted file mode 100644 index 555efd8..0000000 --- a/lib/libc/iconv/iconv.c +++ /dev/null @@ -1,312 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */ - -/*- - * Copyright (c) 2003 Citrus Project, - * Copyright (c) 2009, 2010 Gabor Kovesdan , - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "citrus_types.h" -#include "citrus_module.h" -#include "citrus_esdb.h" -#include "citrus_hash.h" -#include "citrus_iconv.h" - -#include "iconv-internal.h" - -#define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1) - -static iconv_t -__bsd___iconv_open(const char *out, const char *in, struct _citrus_iconv *handle) -{ - const char *out_slashes; - char *out_noslashes; - int ret; - - /* - * Remove anything following a //, as these are options (like - * //ignore, //translate, etc) and we just don't handle them. - * This is for compatibility with software that uses these - * blindly. - */ - out_slashes = strstr(out, "//"); - if (out_slashes != NULL) { - out_noslashes = strndup(out, out_slashes - out); - if (out_noslashes == NULL) { - errno = ENOMEM; - return ((iconv_t)-1); - } - ret = _citrus_iconv_open(&handle, in, out_noslashes); - free(out_noslashes); - } else { - ret = _citrus_iconv_open(&handle, in, out); - } - - if (ret) { - errno = ret == ENOENT ? EINVAL : ret; - return ((iconv_t)-1); - } - - handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE"); - handle->cv_shared->ci_hooks = NULL; - - return ((iconv_t)(void *)handle); -} - -iconv_t -__bsd_iconv_open(const char *out, const char *in) -{ - - return (__bsd___iconv_open(out, in, NULL)); -} - -int -__bsd_iconv_open_into(const char *out, const char *in, iconv_allocation_t *ptr) -{ - struct _citrus_iconv *handle; - - handle = (struct _citrus_iconv *)ptr; - return ((__bsd___iconv_open(out, in, handle) == (iconv_t)-1) ? -1 : 0); -} - -int -__bsd_iconv_close(iconv_t handle) -{ - - if (ISBADF(handle)) { - errno = EBADF; - return (-1); - } - - _citrus_iconv_close((struct _citrus_iconv *)(void *)handle); - - return (0); -} - -size_t -__bsd_iconv(iconv_t handle, const char **in, size_t *szin, char **out, size_t *szout) -{ - size_t ret; - int err; - - if (ISBADF(handle)) { - errno = EBADF; - return ((size_t)-1); - } - - err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle, - in, szin, out, szout, 0, &ret); - if (err) { - errno = err; - ret = (size_t)-1; - } - - return (ret); -} - -size_t -__bsd___iconv(iconv_t handle, const char **in, size_t *szin, char **out, - size_t *szout, uint32_t flags, size_t *invalids) -{ - size_t ret; - int err; - - if (ISBADF(handle)) { - errno = EBADF; - return ((size_t)-1); - } - - err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle, - in, szin, out, szout, flags, &ret); - if (invalids) - *invalids = ret; - if (err) { - errno = err; - ret = (size_t)-1; - } - - return (ret); -} - -int -__bsd___iconv_get_list(char ***rlist, size_t *rsz, bool sorted) -{ - int ret; - - ret = _citrus_esdb_get_list(rlist, rsz, sorted); - if (ret) { - errno = ret; - return (-1); - } - - return (0); -} - -void -__bsd___iconv_free_list(char **list, size_t sz) -{ - - _citrus_esdb_free_list(list, sz); -} - -/* - * GNU-compatibile non-standard interfaces. - */ -static int -qsort_helper(const void *first, const void *second) -{ - const char * const *s1; - const char * const *s2; - - s1 = first; - s2 = second; - return (strcmp(*s1, *s2)); -} - -void -__bsd_iconvlist(int (*do_one) (unsigned int, const char * const *, - void *), void *data) -{ - char **list, **names; - const char * const *np; - char *curitem, *curkey, *slashpos; - size_t sz; - unsigned int i, j; - - i = 0; - - if (__bsd___iconv_get_list(&list, &sz, true)) - list = NULL; - qsort((void *)list, sz, sizeof(char *), qsort_helper); - while (i < sz) { - j = 0; - slashpos = strchr(list[i], '/'); - curkey = (char *)malloc(slashpos - list[i] + 2); - names = (char **)malloc(sz * sizeof(char *)); - if ((curkey == NULL) || (names == NULL)) { - __bsd___iconv_free_list(list, sz); - return; - } - strlcpy(curkey, list[i], slashpos - list[i] + 1); - names[j++] = strdup(curkey); - for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) { - slashpos = strchr(list[i], '/'); - curitem = (char *)malloc(strlen(slashpos) + 1); - if (curitem == NULL) { - __bsd___iconv_free_list(list, sz); - return; - } - strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1); - if (strcmp(curkey, curitem) == 0) { - continue; - } - names[j++] = strdup(curitem); - } - np = (const char * const *)names; - do_one(j, np, data); - free(names); - } - - __bsd___iconv_free_list(list, sz); -} - -__inline const char * -__bsd_iconv_canonicalize(const char *name) -{ - - return (_citrus_iconv_canonicalize(name)); -} - -int -__bsd_iconvctl(iconv_t cd, int request, void *argument) -{ - struct _citrus_iconv *cv; - struct iconv_hooks *hooks; - const char *convname; - char src[PATH_MAX], *dst; - int *i; - - cv = (struct _citrus_iconv *)(void *)cd; - hooks = (struct iconv_hooks *)argument; - i = (int *)argument; - - if (ISBADF(cd)) { - errno = EBADF; - return (-1); - } - - switch (request) { - case ICONV_TRIVIALP: - convname = cv->cv_shared->ci_convname; - dst = strchr(convname, '/'); - - strlcpy(src, convname, dst - convname + 1); - dst++; - if ((convname == NULL) || (src == NULL) || (dst == NULL)) - return (-1); - *i = strcmp(src, dst) == 0 ? 1 : 0; - return (0); - case ICONV_GET_TRANSLITERATE: - *i = 1; - return (0); - case ICONV_SET_TRANSLITERATE: - return ((*i == 1) ? 0 : -1); - case ICONV_GET_DISCARD_ILSEQ: - *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0; - return (0); - case ICONV_SET_DISCARD_ILSEQ: - cv->cv_shared->ci_discard_ilseq = *i; - return (0); - case ICONV_SET_HOOKS: - cv->cv_shared->ci_hooks = hooks; - return (0); - case ICONV_SET_FALLBACKS: - errno = EOPNOTSUPP; - return (-1); - default: - errno = EINVAL; - return (-1); - } -} - -void -__bsd_iconv_set_relocation_prefix(const char *orig_prefix __unused, - const char *curr_prefix __unused) -{ - -} diff --git a/lib/libc_nonshared/Makefile b/lib/libc_nonshared/Makefile index b5ea5f0..07c4f2d 100644 --- a/lib/libc_nonshared/Makefile +++ b/lib/libc_nonshared/Makefile @@ -12,16 +12,8 @@ CFLAGS+=${PICFLAG} -DPIC -fvisibility=hidden LIB= c_nonshared -# So that an empty .a file doesn't cause errors. -SRCS= __stub.c - -.if ${MK_ICONV} == "yes" -SRCS+= __iconv.c __iconv_free_list.c __iconv_get_list.c \ - iconv.c iconv_canonicalize.c iconv_close.c \ - iconv_open.c iconv_open_into.c \ - iconv_set_relocation_prefix.c iconvctl.c iconvlist.c -CFLAGS+=-I${.CURDIR}/../libc/iconv -.endif +.include "Makefile.inc1" +SRCS=${LIBC_NONSHARED_SRCS} .include diff --git a/lib/libc_nonshared/Makefile.inc1 b/lib/libc_nonshared/Makefile.inc1 new file mode 100644 index 0000000..2adfaa9 --- /dev/null +++ b/lib/libc_nonshared/Makefile.inc1 @@ -0,0 +1,12 @@ +# $Id$ + +# So that an empty .a file doesn't cause errors. +LIBC_NONSHARED_SRCS= __stub.c + +.if ${MK_ICONV} == "yes" +LIBC_NONSHARED_SRCS+= __iconv.c __iconv_free_list.c __iconv_get_list.c \ + iconv.c iconv_canonicalize.c iconv_close.c \ + iconv_open.c iconv_open_into.c \ + iconv_set_relocation_prefix.c iconvctl.c iconvlist.c +CFLAGS+=-I${.CURDIR}/../libc/iconv +.endif