diff --git a/src/system/libroot/Jamfile b/src/system/libroot/Jamfile index 06e736c039..9410b27cf6 100644 --- a/src/system/libroot/Jamfile +++ b/src/system/libroot/Jamfile @@ -22,8 +22,10 @@ local librootObjects = posix_gnu_arch_$(TARGET_ARCH).o posix_gnu_ctype.o posix_gnu_ext.o + posix_gnu_iconv.o posix_gnu_libio.o posix_gnu_locale.o + posix_gnu_misc.o posix_gnu_regex.o posix_gnu_stdio.o posix_gnu_stdlib.o diff --git a/src/system/libroot/posix/glibc/Jamfile b/src/system/libroot/posix/glibc/Jamfile index fcdc5f95d0..03929bb6e4 100644 --- a/src/system/libroot/posix/glibc/Jamfile +++ b/src/system/libroot/posix/glibc/Jamfile @@ -3,8 +3,10 @@ SubDir HAIKU_TOP src system libroot posix glibc ; SubInclude HAIKU_TOP src system libroot posix glibc arch ; SubInclude HAIKU_TOP src system libroot posix glibc ctype ; SubInclude HAIKU_TOP src system libroot posix glibc extensions ; +SubInclude HAIKU_TOP src system libroot posix glibc iconv ; SubInclude HAIKU_TOP src system libroot posix glibc locale ; SubInclude HAIKU_TOP src system libroot posix glibc libio ; +SubInclude HAIKU_TOP src system libroot posix glibc misc ; SubInclude HAIKU_TOP src system libroot posix glibc regex ; SubInclude HAIKU_TOP src system libroot posix glibc stdio-common ; SubInclude HAIKU_TOP src system libroot posix glibc stdlib ; diff --git a/src/system/libroot/posix/glibc/iconv/Jamfile b/src/system/libroot/posix/glibc/iconv/Jamfile new file mode 100644 index 0000000000..f64b5e5deb --- /dev/null +++ b/src/system/libroot/posix/glibc/iconv/Jamfile @@ -0,0 +1,23 @@ +SubDir HAIKU_TOP src system libroot posix glibc iconv ; + +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch + $(TARGET_ARCH) ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch generic ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ctype ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc iconv ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ; +#SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc string ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; + +SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ; + +MergeObject posix_gnu_iconv.o : + gconv_builtin.c + gconv_cache.c + gconv_conf.c + gconv_db.c +# gconv_dl.c + gconv_simple.c +; diff --git a/src/system/libroot/posix/glibc/iconv/gconv_cache.c b/src/system/libroot/posix/glibc/iconv/gconv_cache.c index 882acc6fa4..7c45ed87a6 100644 --- a/src/system/libroot/posix/glibc/iconv/gconv_cache.c +++ b/src/system/libroot/posix/glibc/iconv/gconv_cache.c @@ -23,7 +23,7 @@ #include #include #include -#include +//#include #include #include @@ -53,10 +53,11 @@ __gconv_load_cache (void) /* We cannot use the cache if the GCONV_PATH environment variable is set. */ - __gconv_path_envvar = getenv ("GCONV_PATH"); - if (__gconv_path_envvar != NULL) +// __gconv_path_envvar = getenv ("GCONV_PATH"); +// if (__gconv_path_envvar != NULL) return -1; +#if 0 /* See whether the cache file exists. */ fd = __open (GCONV_MODULES_CACHE, O_RDONLY); if (__builtin_expect (fd, 0) == -1) @@ -137,6 +138,7 @@ __gconv_load_cache (void) /* That worked. */ return 0; +#endif } @@ -177,7 +179,7 @@ find_module_idx (const char *str, size_t *idxp) return -1; } - +#if 0 #ifndef STATIC_GCONV static int internal_function @@ -213,6 +215,7 @@ find_module (const char *directory, const char *filename, return status; } #endif +#endif int @@ -240,6 +243,8 @@ internal_function __gconv_lookup_cache (const char *toset, const char *fromset, struct __gconv_step **handle, size_t *nsteps, int flags) { + return __GCONV_NODB; +#if 0 const struct gconvcache_header *header; const char *strtab; size_t fromidx; @@ -433,6 +438,7 @@ __gconv_lookup_cache (const char *toset, const char *fromset, } return __GCONV_OK; +#endif } diff --git a/src/system/libroot/posix/glibc/iconv/gconv_conf.c b/src/system/libroot/posix/glibc/iconv/gconv_conf.c index 746c2245a3..ba36b3871e 100644 --- a/src/system/libroot/posix/glibc/iconv/gconv_conf.c +++ b/src/system/libroot/posix/glibc/iconv/gconv_conf.c @@ -35,9 +35,8 @@ #include #include - /* This is the default path where we look for module lists. */ -static const char default_gconv_path[] = GCONV_PATH; +static const char default_gconv_path[] = ""; //GCONV_PATH; /* The path elements, as determined by the __gconv_get_path function. All path elements end in a slash. */ diff --git a/src/system/libroot/posix/glibc/iconv/gconv_db.c b/src/system/libroot/posix/glibc/iconv/gconv_db.c index 020b556d5e..af6a995947 100644 --- a/src/system/libroot/posix/glibc/iconv/gconv_db.c +++ b/src/system/libroot/posix/glibc/iconv/gconv_db.c @@ -19,7 +19,7 @@ 02111-1307 USA. */ #include -#include +//#include #include #include #include @@ -29,6 +29,8 @@ #include #include +#define STATIC_GCONV + /* Simple data structure for alias mapping. We have two names, `from' and `to'. */ @@ -214,6 +216,7 @@ __gconv_release_step (struct __gconv_step *step) } } +#if 0 static int internal_function gen_steps (struct derivation_step *best, const char *toset, @@ -635,7 +638,7 @@ find_derivation (const char *toset, const char *toset_expand, return result; } - +#endif /* Control of initialization. */ __libc_once_define (static, once); @@ -676,6 +679,8 @@ __gconv_find_transform (const char *toset, const char *fromset, struct __gconv_step **handle, size_t *nsteps, int flags) { + return __GCONV_NOCONV; +#if 0 const char *fromset_expand; const char *toset_expand; int result; @@ -732,6 +737,7 @@ __gconv_find_transform (const char *toset, const char *fromset, return (result == __GCONV_OK ? (*handle == NULL ? __GCONV_NOCONV : __GCONV_OK) : result); +#endif } diff --git a/src/system/libroot/posix/glibc/iconv/gconv_dl.c b/src/system/libroot/posix/glibc/iconv/gconv_dl.c index cc7627aba2..76275291cd 100644 --- a/src/system/libroot/posix/glibc/iconv/gconv_dl.c +++ b/src/system/libroot/posix/glibc/iconv/gconv_dl.c @@ -67,6 +67,8 @@ struct __gconv_loaded_object * internal_function __gconv_find_shlib (const char *name) { + return NULL; +#if 0 struct __gconv_loaded_object *found; void *keyp; @@ -142,6 +144,7 @@ __gconv_find_shlib (const char *name) } return found; +#endif } diff --git a/src/system/libroot/posix/glibc/iconv/gconv_simple.c b/src/system/libroot/posix/glibc/iconv/gconv_simple.c index 69489d892b..e0d14139ba 100644 --- a/src/system/libroot/posix/glibc/iconv/gconv_simple.c +++ b/src/system/libroot/posix/glibc/iconv/gconv_simple.c @@ -1,5 +1,5 @@ /* Simple transformations functions. - Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1997-2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -72,6 +72,7 @@ __gconv_btwoc_ascii (struct __gconv_step *step, unsigned char c) static inline int +__attribute ((always_inline)) internal_ucs4_loop (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, const unsigned char *inend, @@ -86,12 +87,13 @@ internal_ucs4_loop (struct __gconv_step *step, #if __BYTE_ORDER == __LITTLE_ENDIAN /* Sigh, we have to do some real work. */ size_t cnt; + uint32_t *outptr32 = (uint32_t *) outptr; for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) - *((uint32_t *) outptr)++ = bswap_32 (*(const uint32_t *) inptr); + *outptr32++ = bswap_32 (*(const uint32_t *) inptr); *inptrp = inptr; - *outptrp = outptr; + *outptrp = (unsigned char *) outptr32; #elif __BYTE_ORDER == __BIG_ENDIAN /* Simply copy the data. */ *inptrp = inptr + n_convert * 4; @@ -113,6 +115,7 @@ internal_ucs4_loop (struct __gconv_step *step, #ifndef _STRING_ARCH_unaligned static inline int +__attribute ((always_inline)) internal_ucs4_loop_unaligned (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -161,6 +164,7 @@ internal_ucs4_loop_unaligned (struct __gconv_step *step, static inline int +__attribute ((always_inline)) internal_ucs4_loop_single (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -189,13 +193,16 @@ internal_ucs4_loop_single (struct __gconv_step *step, (*outptrp)[2] = state->__value.__wchb[1]; (*outptrp)[3] = state->__value.__wchb[0]; - *outptrp += 4; #elif __BYTE_ORDER == __BIG_ENDIAN /* XXX unaligned */ - *(*((uint32_t **) outptrp)++) = state->__value.__wch; + (*outptrp)[0] = state->__value.__wchb[0]; + (*outptrp)[1] = state->__value.__wchb[1]; + (*outptrp)[2] = state->__value.__wchb[2]; + (*outptrp)[3] = state->__value.__wchb[3]; #else # error "This endianess is not supported." #endif + *outptrp += 4; /* Clear the state buffer. */ state->__count &= ~7; @@ -219,6 +226,7 @@ internal_ucs4_loop_single (struct __gconv_step *step, static inline int +__attribute ((always_inline)) ucs4_internal_loop (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, const unsigned char *inend, @@ -264,7 +272,8 @@ ucs4_internal_loop (struct __gconv_step *step, return __GCONV_ILLEGAL_INPUT; } - *((uint32_t *) outptr)++ = inval; + *((uint32_t *) outptr) = inval; + outptr += sizeof (uint32_t); } *inptrp = inptr; @@ -283,6 +292,7 @@ ucs4_internal_loop (struct __gconv_step *step, #ifndef _STRING_ARCH_unaligned static inline int +__attribute ((always_inline)) ucs4_internal_loop_unaligned (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -352,6 +362,7 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step, static inline int +__attribute ((always_inline)) ucs4_internal_loop_single (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -426,6 +437,7 @@ ucs4_internal_loop_single (struct __gconv_step *step, static inline int +__attribute ((always_inline)) internal_ucs4le_loop (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, const unsigned char *inend, @@ -440,9 +452,11 @@ internal_ucs4le_loop (struct __gconv_step *step, #if __BYTE_ORDER == __BIG_ENDIAN /* Sigh, we have to do some real work. */ size_t cnt; + uint32_t *outptr32 = (uint32_t *) outptr; for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) - *((uint32_t *) outptr)++ = bswap_32 (*(const uint32_t *) inptr); + *outptr32++ = bswap_32 (*(const uint32_t *) inptr); + outptr = (unsigned char *) outptr32; *inptrp = inptr; *outptrp = outptr; @@ -467,6 +481,7 @@ internal_ucs4le_loop (struct __gconv_step *step, #ifndef _STRING_ARCH_unaligned static inline int +__attribute ((always_inline)) internal_ucs4le_loop_unaligned (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -518,6 +533,7 @@ internal_ucs4le_loop_unaligned (struct __gconv_step *step, static inline int +__attribute ((always_inline)) internal_ucs4le_loop_single (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -546,12 +562,17 @@ internal_ucs4le_loop_single (struct __gconv_step *step, (*outptrp)[2] = state->__value.__wchb[1]; (*outptrp)[3] = state->__value.__wchb[0]; - *outptrp += 4; #else /* XXX unaligned */ - *(*((uint32_t **) outptrp)++) = state->__value.__wch; + (*outptrp)[0] = state->__value.__wchb[0]; + (*outptrp)[1] = state->__value.__wchb[1]; + (*outptrp)[2] = state->__value.__wchb[2]; + (*outptrp)[3] = state->__value.__wchb[3]; + #endif + *outptrp += 4; + /* Clear the state buffer. */ state->__count &= ~7; @@ -573,6 +594,7 @@ internal_ucs4le_loop_single (struct __gconv_step *step, static inline int +__attribute ((always_inline)) ucs4le_internal_loop (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, const unsigned char *inend, @@ -616,7 +638,8 @@ ucs4le_internal_loop (struct __gconv_step *step, return __GCONV_ILLEGAL_INPUT; } - *((uint32_t *) outptr)++ = inval; + *((uint32_t *) outptr) = inval; + outptr += sizeof (uint32_t); } *inptrp = inptr; @@ -638,6 +661,7 @@ ucs4le_internal_loop (struct __gconv_step *step, #ifndef _STRING_ARCH_unaligned static inline int +__attribute ((always_inline)) ucs4le_internal_loop_unaligned (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -711,6 +735,7 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step, static inline int +__attribute ((always_inline)) ucs4le_internal_loop_single (struct __gconv_step *step, struct __gconv_step_data *step_data, const unsigned char **inptrp, @@ -796,7 +821,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, } \ else \ /* It's an one byte sequence. */ \ - *((uint32_t *) outptr)++ = *inptr++; \ + *((uint32_t *) outptr) = *inptr++; \ + outptr += sizeof (uint32_t); \ } #define LOOP_NEED_FLAGS #include @@ -826,7 +852,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, } \ else \ /* It's an one byte sequence. */ \ - *outptr++ = *((const uint32_t *) inptr)++; \ + *outptr++ = *((const uint32_t *) inptr); \ + inptr += sizeof (uint32_t); \ } #define LOOP_NEED_FLAGS #include @@ -875,13 +902,12 @@ ucs4le_internal_loop_single (struct __gconv_step *step, start = outptr; \ *outptr = (unsigned char) (~0xff >> step); \ outptr += step; \ - --step; \ do \ { \ - start[step] = 0x80 | (wc & 0x3f); \ + start[--step] = 0x80 | (wc & 0x3f); \ wc >>= 6; \ } \ - while (--step > 0); \ + while (step > 1); \ start[0] |= wc; \ } \ else \ @@ -963,18 +989,17 @@ ucs4le_internal_loop_single (struct __gconv_step *step, } \ else \ { \ - int skipped; \ - \ /* Search the end of this ill-formed UTF-8 character. This \ is the next byte with (x & 0xc0) != 0x80. */ \ - skipped = 0; \ + i = 0; \ do \ - ++skipped; \ - while (inptr + skipped < inend \ - && (*(inptr + skipped) & 0xc0) == 0x80 \ - && skipped < 5); \ + ++i; \ + while (inptr + i < inend \ + && (*(inptr + i) & 0xc0) == 0x80 \ + && i < 5); \ \ - STANDARD_FROM_LOOP_ERR_HANDLER (skipped); \ + errout: \ + STANDARD_FROM_LOOP_ERR_HANDLER (i); \ } \ \ if (__builtin_expect (inptr + cnt > inend, 0)) \ @@ -991,7 +1016,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step, break; \ } \ \ - STANDARD_FROM_LOOP_ERR_HANDLER (i); \ + goto errout; \ } \ \ /* Read the possible remaining bytes. */ \ @@ -1013,14 +1038,15 @@ ucs4le_internal_loop_single (struct __gconv_step *step, if (i < cnt || (cnt > 2 && (ch >> (5 * cnt - 4)) == 0)) \ { \ /* This is an illegal encoding. */ \ - STANDARD_FROM_LOOP_ERR_HANDLER (i); \ + goto errout; \ } \ \ inptr += cnt; \ } \ \ /* Now adjust the pointers and store the result. */ \ - *((uint32_t *) outptr)++ = ch; \ + *((uint32_t *) outptr) = ch; \ + outptr += sizeof (uint32_t); \ } #define LOOP_NEED_FLAGS @@ -1132,7 +1158,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step, #define LOOPFCT FROM_LOOP #define BODY \ { \ - uint16_t u1 = *((const uint16_t *) inptr); \ + uint16_t u1 = get16 (inptr); \ \ if (__builtin_expect (u1 >= 0xd800 && u1 < 0xe000, 0)) \ { \ @@ -1141,7 +1167,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, STANDARD_FROM_LOOP_ERR_HANDLER (2); \ } \ \ - *((uint32_t *) outptr)++ = u1; \ + *((uint32_t *) outptr) = u1; \ + outptr += sizeof (uint32_t); \ inptr += 2; \ } #define LOOP_NEED_FLAGS @@ -1189,7 +1216,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, } \ else \ { \ - *((uint16_t *) outptr)++ = val; \ + put16 (outptr, val); \ + outptr += sizeof (uint16_t); \ inptr += 4; \ } \ } @@ -1214,7 +1242,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step, #define LOOPFCT FROM_LOOP #define BODY \ { \ - uint16_t u1 = bswap_16 (*((const uint16_t *) inptr)); \ + uint16_t u1 = bswap_16 (get16 (inptr)); \ \ if (__builtin_expect (u1 >= 0xd800 && u1 < 0xe000, 0)) \ { \ @@ -1230,7 +1258,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, continue; \ } \ \ - *((uint32_t *) outptr)++ = u1; \ + *((uint32_t *) outptr) = u1; \ + outptr += sizeof (uint32_t); \ inptr += 2; \ } #define LOOP_NEED_FLAGS @@ -1279,7 +1308,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step, } \ else \ { \ - *((uint16_t *) outptr)++ = bswap_16 (val); \ + put16 (outptr, bswap_16 (val)); \ + outptr += sizeof (uint16_t); \ inptr += 4; \ } \ } diff --git a/src/system/libroot/posix/glibc/include/arch/ppc/bits/byteswap.h b/src/system/libroot/posix/glibc/include/arch/ppc/bits/byteswap.h new file mode 100644 index 0000000000..38d8540130 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/ppc/bits/byteswap.h @@ -0,0 +1,84 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2001, 2002 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#ifdef __GNUC__ +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __bsx = (x); \ + ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); })) +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); +} +#endif + +/* Swap bytes in 32 bit value. */ +#ifdef __GNUC__ +# define __bswap_32(x) \ + (__extension__ \ + ({ unsigned int __bsx = (x); \ + ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \ + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); })) +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); +} +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86/bits/byteswap.h b/src/system/libroot/posix/glibc/include/arch/x86/bits/byteswap.h index 0d7d75cb42..33af208888 100644 --- a/src/system/libroot/posix/glibc/include/arch/x86/bits/byteswap.h +++ b/src/system/libroot/posix/glibc/include/arch/x86/bits/byteswap.h @@ -1,5 +1,5 @@ /* Macros to swap the order of bytes in integer values. - Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 2000, 2002, 2003 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 @@ -64,7 +64,8 @@ __bswap_16 (unsigned short int __bsx) # if __GNUC__ >= 2 /* To swap the bytes in a word the i486 processors and up provide the `bswap' opcode. On i386 we have to use three instructions. */ -# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ +# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ + && !defined __pentium4__ # define __bswap_32(x) \ (__extension__ \ ({ register unsigned int __v, __x = (x); \ diff --git a/src/system/libroot/posix/glibc/include/arch/x86/bits/string.h b/src/system/libroot/posix/glibc/include/arch/x86/bits/string.h new file mode 100644 index 0000000000..d181afd48b --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86/bits/string.h @@ -0,0 +1,922 @@ +/* Optimized, inlined string functions. i386 version. + Copyright (C) 1997,1998,1999,2000,2003 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STRING_H +# error "Never use directly; include instead." +#endif + +/* The ix86 processors can access unaligned multi-byte variables. */ +#define _STRING_ARCH_unaligned 1 + + +/* We only provide optimizations if the user selects them and if + GNU CC is used. */ +#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ + && defined __GNUC__ && __GNUC__ >= 2 && !__BOUNDED_POINTERS__ + +#ifndef __STRING_INLINE +# ifdef __cplusplus +# define __STRING_INLINE inline +# else +# define __STRING_INLINE extern __inline +# endif +#endif + + +/* Copy N bytes of SRC to DEST. */ +#define _HAVE_STRING_ARCH_memcpy 1 +#define memcpy(dest, src, n) \ + (__extension__ (__builtin_constant_p (n) \ + ? __memcpy_c ((dest), (src), (n)) \ + : memcpy ((dest), (src), (n)))) +/* This looks horribly ugly, but the compiler can optimize it totally, + as the count is constant. */ +__STRING_INLINE void *__memcpy_c (void *__dest, __const void *__src, + size_t __n); + +__STRING_INLINE void * +__memcpy_c (void *__dest, __const void *__src, size_t __n) +{ + register unsigned long int __d0, __d1, __d2; + union { + unsigned int __ui; + unsigned short int __usi; + unsigned char __uc; + } *__u = __dest; + switch (__n) + { + case 0: + return __dest; + case 1: + __u->__uc = *(const unsigned char *) __src; + return __dest; + case 2: + __u->__usi = *(const unsigned short int *) __src; + return __dest; + case 3: + __u->__usi = *(const unsigned short int *) __src; + __u = (void *) __u + 2; + __u->__uc = *(2 + (const unsigned char *) __src); + return __dest; + case 4: + __u->__ui = *(const unsigned int *) __src; + return __dest; + case 6: + __u->__ui = *(const unsigned int *) __src; + __u = (void *) __u + 4; + __u->__usi = *(2 + (const unsigned short int *) __src); + return __dest; + case 8: + __u->__ui = *(const unsigned int *) __src; + __u = (void *) __u + 4; + __u->__ui = *(1 + (const unsigned int *) __src); + return __dest; + case 12: + __u->__ui = *(const unsigned int *) __src; + __u = (void *) __u + 4; + __u->__ui = *(1 + (const unsigned int *) __src); + __u = (void *) __u + 4; + __u->__ui = *(2 + (const unsigned int *) __src); + return __dest; + case 16: + __u->__ui = *(const unsigned int *) __src; + __u = (void *) __u + 4; + __u->__ui = *(1 + (const unsigned int *) __src); + __u = (void *) __u + 4; + __u->__ui = *(2 + (const unsigned int *) __src); + __u = (void *) __u + 4; + __u->__ui = *(3 + (const unsigned int *) __src); + return __dest; + case 20: + __u->__ui = *(const unsigned int *) __src; + __u = (void *) __u + 4; + __u->__ui = *(1 + (const unsigned int *) __src); + __u = (void *) __u + 4; + __u->__ui = *(2 + (const unsigned int *) __src); + __u = (void *) __u + 4; + __u->__ui = *(3 + (const unsigned int *) __src); + __u = (void *) __u + 4; + __u->__ui = *(4 + (const unsigned int *) __src); + return __dest; + } +#define __COMMON_CODE(x) \ + __asm__ __volatile__ \ + ("cld\n\t" \ + "rep; movsl" \ + x \ + : "=&c" (__d0), "=&D" (__d1), "=&S" (__d2) \ + : "0" (__n / 4), "1" (&__u->__uc), "2" (__src) \ + : "memory"); + + switch (__n % 4) + { + case 0: + __COMMON_CODE (""); + break; + case 1: + __COMMON_CODE ("\n\tmovsb"); + break; + case 2: + __COMMON_CODE ("\n\tmovsw"); + break; + case 3: + __COMMON_CODE ("\n\tmovsw\n\tmovsb"); + break; + } + return __dest; +#undef __COMMON_CODE +} + + +/* Copy N bytes of SRC to DEST, guaranteeing + correct behavior for overlapping strings. */ +#define _HAVE_STRING_ARCH_memmove 1 +#ifndef _FORCE_INLINES +__STRING_INLINE void * +memmove (void *__dest, __const void *__src, size_t __n) +{ + register unsigned long int __d0, __d1, __d2; + if (__dest < __src) + __asm__ __volatile__ + ("cld\n\t" + "rep\n\t" + "movsb" + : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) + : "0" (__n), "1" (__src), "2" (__dest) + : "memory"); + else + __asm__ __volatile__ + ("std\n\t" + "rep\n\t" + "movsb\n\t" + "cld" + : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) + : "0" (__n), "1" (__n - 1 + (const char *) __src), + "2" (__n - 1 + (char *) __dest) + : "memory"); + return __dest; +} +#endif + +/* Set N bytes of S to C. */ +#define _HAVE_STRING_ARCH_memset 1 +#define _USE_STRING_ARCH_memset 1 +#define memset(s, c, n) \ + (__extension__ (__builtin_constant_p (c) \ + ? (__builtin_constant_p (n) \ + ? __memset_cc (s, 0x01010101UL * (unsigned char) (c), n) \ + : __memset_cg (s, 0x01010101UL * (unsigned char) (c), n))\ + : __memset_gg (s, c, n))) + +__STRING_INLINE void *__memset_cc (void *__s, unsigned long int __pattern, + size_t __n); + +__STRING_INLINE void * +__memset_cc (void *__s, unsigned long int __pattern, size_t __n) +{ + register unsigned long int __d0, __d1; + union { + unsigned int __ui; + unsigned short int __usi; + unsigned char __uc; + } *__u = __s; + switch (__n) + { + case 0: + return __s; + case 1: + __u->__uc = __pattern; + return __s; + case 2: + __u->__usi = __pattern; + return __s; + case 3: + __u->__usi = __pattern; + __u = __extension__ ((void *) __u + 2); + __u->__uc = __pattern; + return __s; + case 4: + __u->__ui = __pattern; + return __s; + } +#define __COMMON_CODE(x) \ + __asm__ __volatile__ \ + ("cld\n\t" \ + "rep; stosl" \ + x \ + : "=&c" (__d0), "=&D" (__d1) \ + : "a" (__pattern), "0" (__n / 4), "1" (&__u->__uc) \ + : "memory") + + switch (__n % 4) + { + case 0: + __COMMON_CODE (""); + break; + case 1: + __COMMON_CODE ("\n\tstosb"); + break; + case 2: + __COMMON_CODE ("\n\tstosw"); + break; + case 3: + __COMMON_CODE ("\n\tstosw\n\tstosb"); + break; + } + return __s; +#undef __COMMON_CODE +} + +__STRING_INLINE void *__memset_cg (void *__s, unsigned long __c, size_t __n); + +__STRING_INLINE void * +__memset_cg (void *__s, unsigned long __c, size_t __n) +{ + register unsigned long int __d0, __d1; + __asm__ __volatile__ + ("cld\n\t" + "rep; stosl\n\t" + "testb $2,%b3\n\t" + "je 1f\n\t" + "stosw\n" + "1:\n\t" + "testb $1,%b3\n\t" + "je 2f\n\t" + "stosb\n" + "2:" + : "=&c" (__d0), "=&D" (__d1) + : "a" (__c), "q" (__n), "0" (__n / 4), "1" (__s) + : "memory"); + return __s; +} + +__STRING_INLINE void *__memset_gg (void *__s, char __c, size_t __n); + +__STRING_INLINE void * +__memset_gg (void *__s, char __c, size_t __n) +{ + register unsigned long int __d0, __d1; + __asm__ __volatile__ + ("cld\n\t" + "rep; stosb" + : "=&D" (__d0), "=&c" (__d1) + : "a" (__c), "0" (__s), "1" (__n) + : "memory"); + return __s; +} + + + + +/* Search N bytes of S for C. */ +#define _HAVE_STRING_ARCH_memchr 1 +#ifndef _FORCE_INLINES +__STRING_INLINE void * +memchr (__const void *__s, int __c, size_t __n) +{ + register unsigned long int __d0; + register void *__res; + if (__n == 0) + return NULL; + __asm__ __volatile__ + ("cld\n\t" + "repne; scasb\n\t" + "je 1f\n\t" + "movl $1,%0\n" + "1:" + : "=D" (__res), "=&c" (__d0) + : "a" (__c), "0" (__s), "1" (__n), + "m" ( *(struct { __extension__ char __x[__n]; } *)__s) + : "cc"); + return __res - 1; +} +#endif + +#define _HAVE_STRING_ARCH_memrchr 1 +#ifndef _FORCE_INLINES +__STRING_INLINE void * +__memrchr (__const void *__s, int __c, size_t __n) +{ + register unsigned long int __d0; + register void *__res; + if (__n == 0) + return NULL; + __asm__ __volatile__ + ("std\n\t" + "repne; scasb\n\t" + "je 1f\n\t" + "orl $-1,%0\n" + "1:\tcld\n\t" + "incl %0" + : "=D" (__res), "=&c" (__d0) + : "a" (__c), "0" (__s + __n - 1), "1" (__n), + "m" ( *(struct { __extension__ char __x[__n]; } *)__s) + : "cc"); + return __res; +} +# ifdef __USE_GNU +# define memrchr(s, c, n) __memrchr (s, c, n) +# endif +#endif + +/* Return the length of S. */ +#define _HAVE_STRING_ARCH_strlen 1 +#ifndef _FORCE_INLINES +__STRING_INLINE size_t +strlen (__const char *__str) +{ + register unsigned long int __d0; + register size_t __res; + __asm__ __volatile__ + ("cld\n\t" + "repne; scasb\n\t" + "notl %0" + : "=c" (__res), "=&D" (__d0) + : "1" (__str), "a" (0), "0" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__str) + : "cc"); + return __res - 1; +} +#endif + +/* Copy SRC to DEST. */ +#define _HAVE_STRING_ARCH_strcpy 1 +#ifndef _FORCE_INLINES +__STRING_INLINE char * +strcpy (char *__dest, __const char *__src) +{ + register unsigned long int __d0, __d1; + __asm__ __volatile__ + ("cld\n" + "1:\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (__d0), "=&D" (__d1) + : "0" (__src), "1" (__dest) + : "ax", "memory", "cc"); + return __dest; +} +#endif + +/* Copy no more than N characters of SRC to DEST. */ +#define _HAVE_STRING_ARCH_strncpy 1 +#ifndef _FORCE_INLINES +__STRING_INLINE char * +strncpy (char *__dest, __const char *__src, size_t __n) +{ + register unsigned long int __d0, __d1, __d2; + __asm__ __volatile__ + ("cld\n" + "1:\n\t" + "decl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "rep; stosb\n" + "2:" + : "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) + : "0" (__src), "1" (__dest), "2" (__n) + : "ax", "memory", "cc"); + return __dest; +} +#endif + +/* Append SRC onto DEST. */ +#define _HAVE_STRING_ARCH_strcat 1 +#ifndef _FORCE_INLINES +__STRING_INLINE char * +strcat (char *__dest, __const char *__src) +{ + register unsigned long int __d0, __d1, __d2, __d3; + __asm__ __volatile__ + ("cld\n\t" + "repne; scasb\n\t" + "decl %1\n" + "1:\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (__d0), "=&D" (__d1), "=&c" (__d2), "=&a" (__d3) + : "0" (__src), "1" (__dest), "2" (0xffffffff), "3" (0) + : "memory", "cc"); + return __dest; +} +#endif + +/* Append no more than N characters from SRC onto DEST. */ +#define _HAVE_STRING_ARCH_strncat 1 +#ifndef _FORCE_INLINES +__STRING_INLINE char * +strncat (char *__dest, __const char *__src, size_t __n) +{ + register unsigned long int __d0, __d1, __d2, __d3; + __asm__ __volatile__ + ("cld\n\t" + "repne; scasb\n\t" + "decl %1\n\t" + "movl %4,%2\n" + "1:\n\t" + "decl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "jmp 3f\n" + "2:\n\t" + "xorl %3,%3\n\t" + "stosb\n" + "3:" + : "=&S" (__d0), "=&D" (__d1), "=&c" (__d2), "=&a" (__d3) + : "g" (__n), "0" (__src), "1" (__dest), "2" (0xffffffff), "3" (0) + : "memory", "cc"); + return __dest; +} +#endif + +/* Compare S1 and S2. */ +#define _HAVE_STRING_ARCH_strcmp 1 +#ifndef _FORCE_INLINES +__STRING_INLINE int +strcmp (__const char *__s1, __const char *__s2) +{ + register unsigned long int __d0, __d1; + register int __res; + __asm__ __volatile__ + ("cld\n" + "1:\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\n\t" + "sbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "3:" + : "=a" (__res), "=&S" (__d0), "=&D" (__d1) + : "1" (__s1), "2" (__s2), + "m" ( *(struct { char __x[0xfffffff]; } *)__s1), + "m" ( *(struct { char __x[0xfffffff]; } *)__s2) + : "cc"); + return __res; +} +#endif + +/* Compare N characters of S1 and S2. */ +#define _HAVE_STRING_ARCH_strncmp 1 +#ifndef _FORCE_INLINES +__STRING_INLINE int +strncmp (__const char *__s1, __const char *__s2, size_t __n) +{ + register unsigned long int __d0, __d1, __d2; + register int __res; + __asm__ __volatile__ + ("cld\n" + "1:\n\t" + "decl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\n\t" + "sbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "4:" + : "=a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) + : "1" (__s1), "2" (__s2), "3" (__n), + "m" ( *(struct { __extension__ char __x[__n]; } *)__s1), + "m" ( *(struct { __extension__ char __x[__n]; } *)__s2) + : "cc"); + return __res; +} +#endif + +/* Find the first occurrence of C in S. */ +#define _HAVE_STRING_ARCH_strchr 1 +#define _USE_STRING_ARCH_strchr 1 +#define strchr(s, c) \ + (__extension__ (__builtin_constant_p (c) \ + ? __strchr_c (s, ((c) & 0xff) << 8) \ + : __strchr_g (s, c))) + +__STRING_INLINE char *__strchr_g (__const char *__s, int __c); + +__STRING_INLINE char * +__strchr_g (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "movb %%al,%%ah\n" + "1:\n\t" + "lodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\n\t" + "movl %1,%0" + : "=a" (__res), "=&S" (__d0) + : "0" (__c), "1" (__s), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return __res - 1; +} + +__STRING_INLINE char *__strchr_c (__const char *__s, int __c); + +__STRING_INLINE char * +__strchr_c (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "1:\n\t" + "lodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\n\t" + "movl %1,%0" + : "=a" (__res), "=&S" (__d0) + : "0" (__c), "1" (__s), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return __res - 1; +} + + +/* Find the first occurrence of C in S or the final NUL byte. */ +#define _HAVE_STRING_ARCH_strchrnul 1 +#define __strchrnul(s, c) \ + (__extension__ (__builtin_constant_p (c) \ + ? ((c) == '\0' \ + ? (char *) __rawmemchr (s, c) \ + : __strchrnul_c (s, ((c) & 0xff) << 8)) \ + : __strchrnul_g (s, c))) + +__STRING_INLINE char *__strchrnul_g (__const char *__s, int __c); + +__STRING_INLINE char * +__strchrnul_g (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "movb %%al,%%ah\n" + "1:\n\t" + "lodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "2:\n\t" + "movl %1,%0" + : "=a" (__res), "=&S" (__d0) + : "0" (__c), "1" (__s), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return __res - 1; +} + +__STRING_INLINE char *__strchrnul_c (__const char *__s, int __c); + +__STRING_INLINE char * +__strchrnul_c (__const char *__s, int __c) +{ + register unsigned long int __d0; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "1:\n\t" + "lodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "2:\n\t" + "movl %1,%0" + : "=a" (__res), "=&S" (__d0) + : "0" (__c), "1" (__s), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return __res - 1; +} +#ifdef __USE_GNU +# define strchrnul(s, c) __strchrnul (s, c) +#endif + + +/* Return the length of the initial segment of S which + consists entirely of characters not in REJECT. */ +#define _HAVE_STRING_ARCH_strcspn 1 +#ifndef _FORCE_INLINES +# ifdef __PIC__ +__STRING_INLINE size_t +strcspn (__const char *__s, __const char *__reject) +{ + register unsigned long int __d0, __d1, __d2; + register char *__res; + __asm__ __volatile__ + ("pushl %%ebx\n\t" + "cld\n\t" + "movl %4,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%ebx\n" + "1:\n\t" + "lodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %4,%%edi\n\t" + "movl %%ebx,%%ecx\n\t" + "repne; scasb\n\t" + "jne 1b\n" + "2:\n\t" + "popl %%ebx" + : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) + : "d" (__reject), "0" (__s), "1" (0), "2" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return (__res - 1) - __s; +} +# else +__STRING_INLINE size_t +strcspn (__const char *__s, __const char *__reject) +{ + register unsigned long int __d0, __d1, __d2, __d3; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "movl %5,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%edx\n" + "1:\n\t" + "lodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %5,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne; scasb\n\t" + "jne 1b\n" + "2:" + : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) + : "g" (__reject), "0" (__s), "1" (0), "2" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return (__res - 1) - __s; +} +# endif +#endif + + +/* Return the length of the initial segment of S which + consists entirely of characters in ACCEPT. */ +#define _HAVE_STRING_ARCH_strspn 1 +#ifndef _FORCE_INLINES +# ifdef __PIC__ +__STRING_INLINE size_t +strspn (__const char *__s, __const char *__accept) +{ + register unsigned long int __d0, __d1, __d2; + register char *__res; + __asm__ __volatile__ + ("pushl %%ebx\n\t" + "cld\n\t" + "movl %4,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%ebx\n" + "1:\n\t" + "lodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %4,%%edi\n\t" + "movl %%ebx,%%ecx\n\t" + "repne; scasb\n\t" + "je 1b\n" + "2:\n\t" + "popl %%ebx" + : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) + : "r" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return (__res - 1) - __s; +} +# else +__STRING_INLINE size_t +strspn (__const char *__s, __const char *__accept) +{ + register unsigned long int __d0, __d1, __d2, __d3; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "movl %5,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%edx\n" + "1:\n\t" + "lodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %5,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne; scasb\n\t" + "je 1b\n" + "2:" + : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) + : "g" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return (__res - 1) - __s; +} +# endif +#endif + + +/* Find the first occurrence in S of any character in ACCEPT. */ +#define _HAVE_STRING_ARCH_strpbrk 1 +#ifndef _FORCE_INLINES +# ifdef __PIC__ +__STRING_INLINE char * +strpbrk (__const char *__s, __const char *__accept) +{ + unsigned long int __d0, __d1, __d2; + register char *__res; + __asm__ __volatile__ + ("pushl %%ebx\n\t" + "cld\n\t" + "movl %4,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%ebx\n" + "1:\n\t" + "lodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %4,%%edi\n\t" + "movl %%ebx,%%ecx\n\t" + "repne; scasb\n\t" + "jne 1b\n\t" + "decl %0\n\t" + "jmp 3f\n" + "2:\n\t" + "xorl %0,%0\n" + "3:\n\t" + "popl %%ebx" + : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) + : "r" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return __res; +} +# else +__STRING_INLINE char * +strpbrk (__const char *__s, __const char *__accept) +{ + register unsigned long int __d0, __d1, __d2, __d3; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" + "movl %5,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%edx\n" + "1:\n\t" + "lodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %5,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne; scasb\n\t" + "jne 1b\n\t" + "decl %0\n\t" + "jmp 3f\n" + "2:\n\t" + "xorl %0,%0\n" + "3:" + : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) + : "g" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), + "m" ( *(struct { char __x[0xfffffff]; } *)__s) + : "cc"); + return __res; +} +# endif +#endif + + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +#define _HAVE_STRING_ARCH_strstr 1 +#ifndef _FORCE_INLINES +# ifdef __PIC__ +__STRING_INLINE char * +strstr (__const char *__haystack, __const char *__needle) +{ + register unsigned long int __d0, __d1, __d2; + register char *__res; + __asm__ __volatile__ + ("pushl %%ebx\n\t" + "cld\n\t" \ + "movl %4,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ + "movl %%ecx,%%ebx\n" + "1:\n\t" + "movl %4,%%edi\n\t" + "movl %%esi,%%eax\n\t" + "movl %%ebx,%%ecx\n\t" + "repe; cmpsb\n\t" + "je 2f\n\t" /* also works for empty string, see above */ + "xchgl %%eax,%%esi\n\t" + "incl %%esi\n\t" + "cmpb $0,-1(%%eax)\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "2:\n\t" + "popl %%ebx" + : "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) + : "r" (__needle), "0" (0), "1" (0xffffffff), "2" (__haystack) + : "memory", "cc"); + return __res; +} +# else +__STRING_INLINE char * +strstr (__const char *__haystack, __const char *__needle) +{ + register unsigned long int __d0, __d1, __d2, __d3; + register char *__res; + __asm__ __volatile__ + ("cld\n\t" \ + "movl %5,%%edi\n\t" + "repne; scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ + "movl %%ecx,%%edx\n" + "1:\n\t" + "movl %5,%%edi\n\t" + "movl %%esi,%%eax\n\t" + "movl %%edx,%%ecx\n\t" + "repe; cmpsb\n\t" + "je 2f\n\t" /* also works for empty string, see above */ + "xchgl %%eax,%%esi\n\t" + "incl %%esi\n\t" + "cmpb $0,-1(%%eax)\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "2:" + : "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&d" (__d2), "=&D" (__d3) + : "g" (__needle), "0" (0), "1" (0xffffffff), "2" (__haystack) + : "memory", "cc"); + return __res; +} +# endif +#endif + +#ifndef _FORCE_INLINES +# undef __STRING_INLINE +#endif + +#endif /* use string inlines && GNU CC */ diff --git a/src/system/libroot/posix/glibc/include/bits/stat.h b/src/system/libroot/posix/glibc/include/bits/stat.h new file mode 100644 index 0000000000..58d43e0e30 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/bits/stat.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1992, 1996, 1997, 2000 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* This structure needs to be defined in accordance with the + implementation of __stat, __fstat, and __lstat. */ + +#include + +#if 0 +/* Structure describing file characteristics. */ +struct stat + { + /* These are the members that POSIX.1 requires. */ + + __mode_t st_mode; /* File mode. */ +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __dev_t st_dev; /* Device containing the file. */ + __nlink_t st_nlink; /* Link count. */ + + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group. */ +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + + __time_t st_atime; /* Time of last access. */ + __time_t st_mtime; /* Time of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + + /* This should be defined if there is a `st_blksize' member. */ +#undef _STATBUF_ST_BLKSIZE + }; +#endif + +/* Encoding of the file mode. These are the standard Unix values, + but POSIX.1 does not specify what values should be used. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ + +/* POSIX.1b objects. */ +#define __S_TYPEISMQ(buf) 0 +#define __S_TYPEISSEM(buf) 0 +#define __S_TYPEISSHM(buf) 0 + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __mode_t st_mode; /* File mode. */ + __ino64_t st_ino; /* File serial number. */ + __dev_t st_dev; /* Device. */ + __nlink_t st_nlink; /* Link count. */ + + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __off64_t st_size; /* Size of file, in bytes. */ + + __time_t st_atime; /* Time of last access. */ + __time_t st_mtime; /* Time of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + }; +#endif diff --git a/src/system/libroot/posix/glibc/include/byteswap.h b/src/system/libroot/posix/glibc/include/byteswap.h new file mode 100644 index 0000000000..44507de954 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/byteswap.h @@ -0,0 +1 @@ +#include diff --git a/src/system/libroot/posix/glibc/include/fcntl.h b/src/system/libroot/posix/glibc/include/fcntl.h index 10e44e593f..41b7516a7e 100644 --- a/src/system/libroot/posix/glibc/include/fcntl.h +++ b/src/system/libroot/posix/glibc/include/fcntl.h @@ -1,5 +1,7 @@ #ifndef _FCNTL_H + #include_next +#include /* Now define the internal interfaces. */ extern int __open64 (__const char *__file, int __oflag, ...); diff --git a/src/system/libroot/posix/glibc/include/search.h b/src/system/libroot/posix/glibc/include/search.h new file mode 100644 index 0000000000..e82f02832b --- /dev/null +++ b/src/system/libroot/posix/glibc/include/search.h @@ -0,0 +1,19 @@ +#ifndef _SEARCH_H +#include + +libc_hidden_proto (hcreate_r) +libc_hidden_proto (hdestroy_r) +libc_hidden_proto (hsearch_r) +libc_hidden_proto (lfind) + +/* Now define the internal interfaces. */ +extern void __hdestroy (void); +extern void *__tsearch (__const void *__key, void **__rootp, + __compar_fn_t compar); +extern void *__tfind (__const void *__key, void *__const *__rootp, + __compar_fn_t compar); +extern void *__tdelete (__const void *__key, void **__rootp, + __compar_fn_t compar); +extern void __twalk (__const void *__root, __action_fn_t action); +extern void __tdestroy (void *__root, __free_fn_t freefct); +#endif diff --git a/src/system/libroot/posix/glibc/include/string.h b/src/system/libroot/posix/glibc/include/string.h index f4712367ca..eb7cf24e8a 100644 --- a/src/system/libroot/posix/glibc/include/string.h +++ b/src/system/libroot/posix/glibc/include/string.h @@ -7,6 +7,11 @@ #define __memcpy(to, from, size) memcpy(to, from, size) #define __strchrnul(string, character) strchrnul(string, character) #define __strnlen strnlen +#define __strdup strdup +#define __strndup strndup +#define __stpcpy stpcpy +#define __strtok_r strtok_r +#define __strcasecmp strcasecmp static inline char * __strerror_r(int error, char *buffer, size_t bufferSize) @@ -24,4 +29,26 @@ __mempcpy(void *to, const void *from, size_t size) return (unsigned char *)to + size; } +#undef strdupa +#define strdupa(s) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = strlen (__old) + 1; \ + char *__new = (char *) __builtin_alloca (__len); \ + (char *) memcpy (__new, __old, __len); \ + })) + +/* Alternative version which doesn't pollute glibc's namespace. */ +#undef strndupa +#define strndupa(s, n) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = __strnlen (__old, (n)); \ + char *__new = (char *) __builtin_alloca (__len + 1); \ + __new[__len] = '\0'; \ + (char *) memcpy (__new, __old, __len); \ + })) + #endif /* _LIBC_STRING_H */ diff --git a/src/system/libroot/posix/glibc/include/sys/stat.h b/src/system/libroot/posix/glibc/include/sys/stat.h new file mode 100644 index 0000000000..43d26864ab --- /dev/null +++ b/src/system/libroot/posix/glibc/include/sys/stat.h @@ -0,0 +1,52 @@ +#ifndef _SYS_STAT_H +#include_next +#define _SYS_STAT_H 1 +#define _STAT_VER 0 +#include + +/* Now define the internal interfaces. */ +extern int __stat (__const char *__file, struct stat *__buf); +extern int __fstat (int __fd, struct stat *__buf); +extern int __lstat (__const char *__file, struct stat *__buf); +extern int __chmod (__const char *__file, __mode_t __mode); +extern int __fchmod (int __fd, __mode_t __mode); +extern __mode_t __umask (__mode_t __mask); +extern int __mkdir (__const char *__path, __mode_t __mode); +extern int __mknod (__const char *__path, + __mode_t __mode, __dev_t __dev); +#if 0 +#if !defined NOT_IN_libc || defined IS_IN_rtld +hidden_proto (__fxstat) +hidden_proto (__fxstat64) +hidden_proto (__lxstat) +hidden_proto (__lxstat64) +hidden_proto (__xstat) +hidden_proto (__xstat64) +#endif +extern __inline__ int __stat (__const char *__path, struct stat *__statbuf) +{ + return __xstat (_STAT_VER, __path, __statbuf); +} +libc_hidden_proto (__xmknod) +extern __inline__ int __mknod (__const char *__path, __mode_t __mode, + __dev_t __dev) +{ + return __xmknod (_MKNOD_VER, __path, __mode, &__dev); +} + + +/* The `stat', `fstat', `lstat' functions have to be handled special since + even while not compiling the library with optimization calls to these + functions in the shared library must reference the `xstat' etc functions. + We have to use macros but we cannot define them in the normal headers + since on user level we must use real functions. */ +#define stat(fname, buf) __xstat (_STAT_VER, fname, buf) +#define lstat(fname, buf) __lxstat (_STAT_VER, fname, buf) +#define __lstat(fname, buf) __lxstat (_STAT_VER, fname, buf) +#define lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf) +#define stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) +#define fstat64(fd, buf) __fxstat64 (_STAT_VER, fd, buf) +#define fstat(fd, buf) __fxstat (_STAT_VER, fd, buf) +#define __fstat(fd, buf) __fxstat (_STAT_VER, fd, buf) +#endif +#endif diff --git a/src/system/libroot/posix/glibc/include/unistd.h b/src/system/libroot/posix/glibc/include/unistd.h index b48aa08ea4..e0571c7915 100644 --- a/src/system/libroot/posix/glibc/include/unistd.h +++ b/src/system/libroot/posix/glibc/include/unistd.h @@ -22,4 +22,7 @@ #define __unlink(buf) \ unlink(buf) +#define __getcwd(buf, size) \ + getcwd(buf, size) + #endif /* _LIBC_UNISTD_H */ diff --git a/src/system/libroot/posix/glibc/libio/Jamfile b/src/system/libroot/posix/glibc/libio/Jamfile index cd82c91285..141cc454fe 100644 --- a/src/system/libroot/posix/glibc/libio/Jamfile +++ b/src/system/libroot/posix/glibc/libio/Jamfile @@ -7,6 +7,7 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc stdio-common ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ; +#SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc string ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc iconv ; @@ -14,7 +15,10 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc iconv ; # obprintf() is also disabled, because we don't have # obstack functionality +SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ; + MergeObject posix_gnu_libio.o : + __fsetlocking.c clearerr.c clearerr_u.c fcloseall.c diff --git a/src/system/libroot/posix/glibc/libio/__fsetlocking.c b/src/system/libroot/posix/glibc/libio/__fsetlocking.c new file mode 100644 index 0000000000..0542e08dbe --- /dev/null +++ b/src/system/libroot/posix/glibc/libio/__fsetlocking.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2000, 2002 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef __fsetlocking + +int +__fsetlocking (FILE *fp, int type) +{ + int result = ((fp->_flags & _IO_USER_LOCK) + ? FSETLOCKING_BYCALLER : FSETLOCKING_INTERNAL); + + if (type != FSETLOCKING_QUERY) + { + fp->_flags &= ~_IO_USER_LOCK; + if (type == FSETLOCKING_BYCALLER) + fp->_flags |= _IO_USER_LOCK; + } + + return result; +} +INTDEF(__fsetlocking) diff --git a/src/system/libroot/posix/glibc/locale/Jamfile b/src/system/libroot/posix/glibc/locale/Jamfile index 9b4d4df11e..00e0f2b492 100644 --- a/src/system/libroot/posix/glibc/locale/Jamfile +++ b/src/system/libroot/posix/glibc/locale/Jamfile @@ -7,7 +7,7 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; -SubDirCcFlags -DLOCALEDIR=\'\"/share/locale\"\' ; +SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO -DLOCALEDIR=\'\"/share/locale\"\' ; MergeObject posix_gnu_locale.o : C-address.c @@ -39,4 +39,5 @@ MergeObject posix_gnu_locale.o : # lc-time.c mb_cur_max.c # setlocale.c + xlocale.c ; diff --git a/src/system/libroot/posix/glibc/misc/Jamfile b/src/system/libroot/posix/glibc/misc/Jamfile new file mode 100644 index 0000000000..b2791143c9 --- /dev/null +++ b/src/system/libroot/posix/glibc/misc/Jamfile @@ -0,0 +1,17 @@ +SubDir HAIKU_TOP src system libroot posix glibc misc ; + +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch + $(TARGET_ARCH) ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch generic ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include ; +#SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ; +#SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc wcsmbs ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc misc ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; + +SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ; + +MergeObject posix_gnu_misc.o : + tsearch.c +; diff --git a/src/system/libroot/posix/glibc/misc/search.h b/src/system/libroot/posix/glibc/misc/search.h new file mode 100644 index 0000000000..2ffba697b0 --- /dev/null +++ b/src/system/libroot/posix/glibc/misc/search.h @@ -0,0 +1,175 @@ +/* Declarations for System V style searching functions. + Copyright (C) 1995-1999, 2000 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEARCH_H +#define _SEARCH_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Prototype structure for a linked-list data structure. + This is the type used by the `insque' and `remque' functions. */ + +# ifdef __USE_GNU +struct qelem + { + struct qelem *q_forw; + struct qelem *q_back; + char q_data[1]; + }; +# endif + + +/* Insert ELEM into a doubly-linked list, after PREV. */ +extern void insque (void *__elem, void *__prev) __THROW; + +/* Unlink ELEM from the doubly-linked list that it is in. */ +extern void remque (void *__elem) __THROW; +#endif + + +/* For use with hsearch(3). */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (__const void *, __const void *); + +# ifdef __USE_GNU +typedef __compar_fn_t comparison_fn_t; +# endif +#endif + +/* Action which shall be performed in the call the hsearch. */ +typedef enum + { + FIND, + ENTER + } +ACTION; + +typedef struct entry + { + char *key; + void *data; + } +ENTRY; + +/* Opaque type for internal use. */ +struct _ENTRY; + +/* Family of hash table handling functions. The functions also + have reentrant counterparts ending with _r. The non-reentrant + functions all work on a signle internal hashing table. */ + +/* Search for entry matching ITEM.key in internal hash table. If + ACTION is `FIND' return found entry or signal error by returning + NULL. If ACTION is `ENTER' replace existing data (if any) with + ITEM.data. */ +extern ENTRY *hsearch (ENTRY __item, ACTION __action) __THROW; + +/* Create a new hashing table which will at most contain NEL elements. */ +extern int hcreate (size_t __nel) __THROW; + +/* Destroy current internal hashing table. */ +extern void hdestroy (void) __THROW; + +#ifdef __USE_GNU +/* Data type for reentrant functions. */ +struct hsearch_data + { + struct _ENTRY *table; + unsigned int size; + unsigned int filled; + }; + +/* Reentrant versions which can handle multiple hashing tables at the + same time. */ +extern int hsearch_r (ENTRY __item, ACTION __action, ENTRY **__retval, + struct hsearch_data *__htab) __THROW; +extern int hcreate_r (size_t __nel, struct hsearch_data *__htab) __THROW; +extern void hdestroy_r (struct hsearch_data *__htab) __THROW; +#endif + + +/* The tsearch routines are very interesting. They make many + assumptions about the compiler. It assumes that the first field + in node must be the "key" field, which points to the datum. + Everything depends on that. */ +/* For tsearch */ +typedef enum +{ + preorder, + postorder, + endorder, + leaf +} +VISIT; + +/* Search for an entry matching the given KEY in the tree pointed to + by *ROOTP and insert a new element if not found. */ +extern void *tsearch (__const void *__key, void **__rootp, + __compar_fn_t __compar); + +/* Search for an entry matching the given KEY in the tree pointed to + by *ROOTP. If no matching entry is available return NULL. */ +extern void *tfind (__const void *__key, void *__const *__rootp, + __compar_fn_t __compar); + +/* Remove the element matching KEY from the tree pointed to by *ROOTP. */ +extern void *tdelete (__const void *__restrict __key, + void **__restrict __rootp, + __compar_fn_t __compar); + +#ifndef __ACTION_FN_T +# define __ACTION_FN_T +typedef void (*__action_fn_t) (__const void *__nodep, VISIT __value, + int __level); +#endif + +/* Walk through the whole tree and call the ACTION callback for every node + or leaf. */ +extern void twalk (__const void *__root, __action_fn_t __action); + +#ifdef __USE_GNU +/* Callback type for function to free a tree node. If the keys are atomic + data this function should do nothing. */ +typedef void (*__free_fn_t) (void *__nodep); + +/* Destroy the whole tree, call FREEFCT for each node or leaf. */ +extern void tdestroy (void *__root, __free_fn_t __freefct); +#endif + + +/* Perform linear search for KEY by comparing by COMPAR in an array + [BASE,BASE+NMEMB*SIZE). */ +extern void *lfind (__const void *__key, __const void *__base, + size_t *__nmemb, size_t __size, __compar_fn_t __compar); + +/* Perform linear search for KEY by comparing by COMPAR function in + array [BASE,BASE+NMEMB*SIZE) and insert entry if not found. */ +extern void *lsearch (__const void *__key, void *__base, + size_t *__nmemb, size_t __size, __compar_fn_t __compar); + +__END_DECLS + +#endif /* search.h */ diff --git a/src/system/libroot/posix/glibc/misc/tsearch.c b/src/system/libroot/posix/glibc/misc/tsearch.c new file mode 100644 index 0000000000..6bca0a9f67 --- /dev/null +++ b/src/system/libroot/posix/glibc/misc/tsearch.c @@ -0,0 +1,656 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bernd Schmidt , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Tree search for red/black trees. + The algorithm for adding nodes is taken from one of the many "Algorithms" + books by Robert Sedgewick, although the implementation differs. + The algorithm for deleting nodes can probably be found in a book named + "Introduction to Algorithms" by Cormen/Leiserson/Rivest. At least that's + the book that my professor took most algorithms from during the "Data + Structures" course... + + Totally public domain. */ + +/* Red/black trees are binary trees in which the edges are colored either red + or black. They have the following properties: + 1. The number of black edges on every path from the root to a leaf is + constant. + 2. No two red edges are adjacent. + Therefore there is an upper bound on the length of every path, it's + O(log n) where n is the number of nodes in the tree. No path can be longer + than 1+2*P where P is the length of the shortest path in the tree. + Useful for the implementation: + 3. If one of the children of a node is NULL, then the other one is red + (if it exists). + + In the implementation, not the edges are colored, but the nodes. The color + interpreted as the color of the edge leading to this node. The color is + meaningless for the root node, but we color the root node black for + convenience. All added nodes are red initially. + + Adding to a red/black tree is rather easy. The right place is searched + with a usual binary tree search. Additionally, whenever a node N is + reached that has two red successors, the successors are colored black and + the node itself colored red. This moves red edges up the tree where they + pose less of a problem once we get to really insert the new node. Changing + N's color to red may violate rule 2, however, so rotations may become + necessary to restore the invariants. Adding a new red leaf may violate + the same rule, so afterwards an additional check is run and the tree + possibly rotated. + + Deleting is hairy. There are mainly two nodes involved: the node to be + deleted (n1), and another node that is to be unchained from the tree (n2). + If n1 has a successor (the node with a smallest key that is larger than + n1), then the successor becomes n2 and its contents are copied into n1, + otherwise n1 becomes n2. + Unchaining a node may violate rule 1: if n2 is black, one subtree is + missing one black edge afterwards. The algorithm must try to move this + error upwards towards the root, so that the subtree that does not have + enough black edges becomes the whole tree. Once that happens, the error + has disappeared. It may not be necessary to go all the way up, since it + is possible that rotations and recoloring can fix the error before that. + + Although the deletion algorithm must walk upwards through the tree, we + do not store parent pointers in the nodes. Instead, delete allocates a + small array of parent pointers and fills it while descending the tree. + Since we know that the length of a path is O(log n), where n is the number + of nodes, this is likely to use less memory. */ + +/* Tree rotations look like this: + A C + / \ / \ + B C A G + / \ / \ --> / \ + D E F G B F + / \ + D E + + In this case, A has been rotated left. This preserves the ordering of the + binary tree. */ + +#include +#include +#include + +typedef struct node_t +{ + /* Callers expect this to be the first element in the structure - do not + move! */ + const void *key; + struct node_t *left; + struct node_t *right; + unsigned int red:1; +} *node; +typedef const struct node_t *const_node; + +#undef DEBUGGING + +#ifdef DEBUGGING + +/* Routines to check tree invariants. */ + +#include + +#define CHECK_TREE(a) check_tree(a) + +static void +check_tree_recurse (node p, int d_sofar, int d_total) +{ + if (p == NULL) + { + assert (d_sofar == d_total); + return; + } + + check_tree_recurse (p->left, d_sofar + (p->left && !p->left->red), d_total); + check_tree_recurse (p->right, d_sofar + (p->right && !p->right->red), d_total); + if (p->left) + assert (!(p->left->red && p->red)); + if (p->right) + assert (!(p->right->red && p->red)); +} + +static void +check_tree (node root) +{ + int cnt = 0; + node p; + if (root == NULL) + return; + root->red = 0; + for(p = root->left; p; p = p->left) + cnt += !p->red; + check_tree_recurse (root, 0, cnt); +} + + +#else + +#define CHECK_TREE(a) + +#endif + +/* Possibly "split" a node with two red successors, and/or fix up two red + edges in a row. ROOTP is a pointer to the lowest node we visited, PARENTP + and GPARENTP pointers to its parent/grandparent. P_R and GP_R contain the + comparison values that determined which way was taken in the tree to reach + ROOTP. MODE is 1 if we need not do the split, but must check for two red + edges between GPARENTP and ROOTP. */ +static void +maybe_split_for_insert (node *rootp, node *parentp, node *gparentp, + int p_r, int gp_r, int mode) +{ + node root = *rootp; + node *rp, *lp; + rp = &(*rootp)->right; + lp = &(*rootp)->left; + + /* See if we have to split this node (both successors red). */ + if (mode == 1 + || ((*rp) != NULL && (*lp) != NULL && (*rp)->red && (*lp)->red)) + { + /* This node becomes red, its successors black. */ + root->red = 1; + if (*rp) + (*rp)->red = 0; + if (*lp) + (*lp)->red = 0; + + /* If the parent of this node is also red, we have to do + rotations. */ + if (parentp != NULL && (*parentp)->red) + { + node gp = *gparentp; + node p = *parentp; + /* There are two main cases: + 1. The edge types (left or right) of the two red edges differ. + 2. Both red edges are of the same type. + There exist two symmetries of each case, so there is a total of + 4 cases. */ + if ((p_r > 0) != (gp_r > 0)) + { + /* Put the child at the top of the tree, with its parent + and grandparent as successors. */ + p->red = 1; + gp->red = 1; + root->red = 0; + if (p_r < 0) + { + /* Child is left of parent. */ + p->left = *rp; + *rp = p; + gp->right = *lp; + *lp = gp; + } + else + { + /* Child is right of parent. */ + p->right = *lp; + *lp = p; + gp->left = *rp; + *rp = gp; + } + *gparentp = root; + } + else + { + *gparentp = *parentp; + /* Parent becomes the top of the tree, grandparent and + child are its successors. */ + p->red = 0; + gp->red = 1; + if (p_r < 0) + { + /* Left edges. */ + gp->left = p->right; + p->right = gp; + } + else + { + /* Right edges. */ + gp->right = p->left; + p->left = gp; + } + } + } + } +} + +/* Find or insert datum into search tree. + KEY is the key to be located, ROOTP is the address of tree root, + COMPAR the ordering function. */ +void * +__tsearch (const void *key, void **vrootp, __compar_fn_t compar) +{ + node q; + node *parentp = NULL, *gparentp = NULL; + node *rootp = (node *) vrootp; + node *nextp; + int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler. */ + + if (rootp == NULL) + return NULL; + + /* This saves some additional tests below. */ + if (*rootp != NULL) + (*rootp)->red = 0; + + CHECK_TREE (*rootp); + + nextp = rootp; + while (*nextp != NULL) + { + node root = *rootp; + r = (*compar) (key, root->key); + if (r == 0) + return root; + + maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0); + /* If that did any rotations, parentp and gparentp are now garbage. + That doesn't matter, because the values they contain are never + used again in that case. */ + + nextp = r < 0 ? &root->left : &root->right; + if (*nextp == NULL) + break; + + gparentp = parentp; + parentp = rootp; + rootp = nextp; + + gp_r = p_r; + p_r = r; + } + + q = (struct node_t *) malloc (sizeof (struct node_t)); + if (q != NULL) + { + *nextp = q; /* link new node to old */ + q->key = key; /* initialize new node */ + q->red = 1; + q->left = q->right = NULL; + } + if (nextp != rootp) + /* There may be two red edges in a row now, which we must avoid by + rotating the tree. */ + maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1); + + return q; +} +weak_alias (__tsearch, tsearch) + + +/* Find datum in search tree. + KEY is the key to be located, ROOTP is the address of tree root, + COMPAR the ordering function. */ +void * +__tfind (key, vrootp, compar) + const void *key; + void *const *vrootp; + __compar_fn_t compar; +{ + node *rootp = (node *) vrootp; + + if (rootp == NULL) + return NULL; + + CHECK_TREE (*rootp); + + while (*rootp != NULL) + { + node root = *rootp; + int r; + + r = (*compar) (key, root->key); + if (r == 0) + return root; + + rootp = r < 0 ? &root->left : &root->right; + } + return NULL; +} +weak_alias (__tfind, tfind) + + +/* Delete node with given key. + KEY is the key to be deleted, ROOTP is the address of the root of tree, + COMPAR the comparison function. */ +void * +__tdelete (const void *key, void **vrootp, __compar_fn_t compar) +{ + node p, q, r, retval; + int cmp; + node *rootp = (node *) vrootp; + node root, unchained; + /* Stack of nodes so we remember the parents without recursion. It's + _very_ unlikely that there are paths longer than 40 nodes. The tree + would need to have around 250.000 nodes. */ + int stacksize = 40; + int sp = 0; + node **nodestack = alloca (sizeof (node *) * stacksize); + + if (rootp == NULL) + return NULL; + p = *rootp; + if (p == NULL) + return NULL; + + CHECK_TREE (p); + + while ((cmp = (*compar) (key, (*rootp)->key)) != 0) + { + if (sp == stacksize) + { + node **newstack; + stacksize += 20; + newstack = alloca (sizeof (node *) * stacksize); + nodestack = memcpy (newstack, nodestack, sp * sizeof (node *)); + } + + nodestack[sp++] = rootp; + p = *rootp; + rootp = ((cmp < 0) + ? &(*rootp)->left + : &(*rootp)->right); + if (*rootp == NULL) + return NULL; + } + + /* This is bogus if the node to be deleted is the root... this routine + really should return an integer with 0 for success, -1 for failure + and errno = ESRCH or something. */ + retval = p; + + /* We don't unchain the node we want to delete. Instead, we overwrite + it with its successor and unchain the successor. If there is no + successor, we really unchain the node to be deleted. */ + + root = *rootp; + + r = root->right; + q = root->left; + + if (q == NULL || r == NULL) + unchained = root; + else + { + node *parent = rootp, *up = &root->right; + for (;;) + { + if (sp == stacksize) + { + node **newstack; + stacksize += 20; + newstack = alloca (sizeof (node *) * stacksize); + nodestack = memcpy (newstack, nodestack, sp * sizeof (node *)); + } + nodestack[sp++] = parent; + parent = up; + if ((*up)->left == NULL) + break; + up = &(*up)->left; + } + unchained = *up; + } + + /* We know that either the left or right successor of UNCHAINED is NULL. + R becomes the other one, it is chained into the parent of UNCHAINED. */ + r = unchained->left; + if (r == NULL) + r = unchained->right; + if (sp == 0) + *rootp = r; + else + { + q = *nodestack[sp-1]; + if (unchained == q->right) + q->right = r; + else + q->left = r; + } + + if (unchained != root) + root->key = unchained->key; + if (!unchained->red) + { + /* Now we lost a black edge, which means that the number of black + edges on every path is no longer constant. We must balance the + tree. */ + /* NODESTACK now contains all parents of R. R is likely to be NULL + in the first iteration. */ + /* NULL nodes are considered black throughout - this is necessary for + correctness. */ + while (sp > 0 && (r == NULL || !r->red)) + { + node *pp = nodestack[sp - 1]; + p = *pp; + /* Two symmetric cases. */ + if (r == p->left) + { + /* Q is R's brother, P is R's parent. The subtree with root + R has one black edge less than the subtree with root Q. */ + q = p->right; + if (q != NULL && q->red) + { + /* If Q is red, we know that P is black. We rotate P left + so that Q becomes the top node in the tree, with P below + it. P is colored red, Q is colored black. + This action does not change the black edge count for any + leaf in the tree, but we will be able to recognize one + of the following situations, which all require that Q + is black. */ + q->red = 0; + p->red = 1; + /* Left rotate p. */ + p->right = q->left; + q->left = p; + *pp = q; + /* Make sure pp is right if the case below tries to use + it. */ + nodestack[sp++] = pp = &q->left; + q = p->right; + } + /* We know that Q can't be NULL here. We also know that Q is + black. */ + if ((q->left == NULL || !q->left->red) + && (q->right == NULL || !q->right->red)) + { + /* Q has two black successors. We can simply color Q red. + The whole subtree with root P is now missing one black + edge. Note that this action can temporarily make the + tree invalid (if P is red). But we will exit the loop + in that case and set P black, which both makes the tree + valid and also makes the black edge count come out + right. If P is black, we are at least one step closer + to the root and we'll try again the next iteration. */ + q->red = 1; + r = p; + } + else + { + /* Q is black, one of Q's successors is red. We can + repair the tree with one operation and will exit the + loop afterwards. */ + if (q->right == NULL || !q->right->red) + { + /* The left one is red. We perform the same action as + in maybe_split_for_insert where two red edges are + adjacent but point in different directions: + Q's left successor (let's call it Q2) becomes the + top of the subtree we are looking at, its parent (Q) + and grandparent (P) become its successors. The former + successors of Q2 are placed below P and Q. + P becomes black, and Q2 gets the color that P had. + This changes the black edge count only for node R and + its successors. */ + node q2 = q->left; + q2->red = p->red; + p->right = q2->left; + q->left = q2->right; + q2->right = q; + q2->left = p; + *pp = q2; + p->red = 0; + } + else + { + /* It's the right one. Rotate P left. P becomes black, + and Q gets the color that P had. Q's right successor + also becomes black. This changes the black edge + count only for node R and its successors. */ + q->red = p->red; + p->red = 0; + + q->right->red = 0; + + /* left rotate p */ + p->right = q->left; + q->left = p; + *pp = q; + } + + /* We're done. */ + sp = 1; + r = NULL; + } + } + else + { + /* Comments: see above. */ + q = p->left; + if (q != NULL && q->red) + { + q->red = 0; + p->red = 1; + p->left = q->right; + q->right = p; + *pp = q; + nodestack[sp++] = pp = &q->right; + q = p->left; + } + if ((q->right == NULL || !q->right->red) + && (q->left == NULL || !q->left->red)) + { + q->red = 1; + r = p; + } + else + { + if (q->left == NULL || !q->left->red) + { + node q2 = q->right; + q2->red = p->red; + p->left = q2->right; + q->right = q2->left; + q2->left = q; + q2->right = p; + *pp = q2; + p->red = 0; + } + else + { + q->red = p->red; + p->red = 0; + q->left->red = 0; + p->left = q->right; + q->right = p; + *pp = q; + } + sp = 1; + r = NULL; + } + } + --sp; + } + if (r != NULL) + r->red = 0; + } + + free (unchained); + return retval; +} +weak_alias (__tdelete, tdelete) + + +/* Walk the nodes of a tree. + ROOT is the root of the tree to be walked, ACTION the function to be + called at each node. LEVEL is the level of ROOT in the whole tree. */ +static void +internal_function +trecurse (const void *vroot, __action_fn_t action, int level) +{ + const_node root = (const_node) vroot; + + if (root->left == NULL && root->right == NULL) + (*action) (root, leaf, level); + else + { + (*action) (root, preorder, level); + if (root->left != NULL) + trecurse (root->left, action, level + 1); + (*action) (root, postorder, level); + if (root->right != NULL) + trecurse (root->right, action, level + 1); + (*action) (root, endorder, level); + } +} + + +/* Walk the nodes of a tree. + ROOT is the root of the tree to be walked, ACTION the function to be + called at each node. */ +void +__twalk (const void *vroot, __action_fn_t action) +{ + const_node root = (const_node) vroot; + + CHECK_TREE (root); + + if (root != NULL && action != NULL) + trecurse (root, action, 0); +} +weak_alias (__twalk, twalk) + + +/* The standardized functions miss an important functionality: the + tree cannot be removed easily. We provide a function to do this. */ +static void +internal_function +tdestroy_recurse (node root, __free_fn_t freefct) +{ + if (root->left != NULL) + tdestroy_recurse (root->left, freefct); + if (root->right != NULL) + tdestroy_recurse (root->right, freefct); + (*freefct) ((void *) root->key); + /* Free the node itself. */ + free (root); +} + +void +__tdestroy (void *vroot, __free_fn_t freefct) +{ + node root = (node) vroot; + + CHECK_TREE (root); + + if (root != NULL) + tdestroy_recurse (root, freefct); +} +weak_alias (__tdestroy, tdestroy) diff --git a/src/system/libroot/posix/glibc/wcsmbs/Jamfile b/src/system/libroot/posix/glibc/wcsmbs/Jamfile index 7094bd5b47..a72907ab0f 100644 --- a/src/system/libroot/posix/glibc/wcsmbs/Jamfile +++ b/src/system/libroot/posix/glibc/wcsmbs/Jamfile @@ -9,6 +9,7 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc wcsmbs ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc iconv ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc stdlib ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ctype ; SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ; diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcsmbsload.c b/src/system/libroot/posix/glibc/wcsmbs/wcsmbsload.c index 74f62d36f9..fe66bea99f 100644 --- a/src/system/libroot/posix/glibc/wcsmbs/wcsmbsload.c +++ b/src/system/libroot/posix/glibc/wcsmbs/wcsmbsload.c @@ -28,16 +28,6 @@ #include #include -void -internal_function -__wcsmbs_load_conv (const struct locale_data *new_category) -{ -} - -static void __attribute__ ((unused)) -free_mem (void) -{ -} /* Last loaded locale for LC_CTYPE. We initialize for the C locale which is enabled at startup. */ @@ -53,7 +43,7 @@ static struct __gconv_step to_wc = .__counter = INT_MAX, .__from_name = (char *) "ANSI_X3.4-1968//TRANSLIT", .__to_name = (char *) "INTERNAL", - .__fct = NULL, // __gconv_transform_ascii_internal, + .__fct = __gconv_transform_ascii_internal, .__init_fct = NULL, .__end_fct = NULL, .__min_needed_from = 1, @@ -71,7 +61,7 @@ static struct __gconv_step to_mb = .__counter = INT_MAX, .__from_name = (char *) "INTERNAL", .__to_name = (char *) "ANSI_X3.4-1968//TRANSLIT", - .__fct = NULL, // __gconv_transform_internal_ascii, + .__fct = __gconv_transform_internal_ascii, .__init_fct = NULL, .__end_fct = NULL, .__min_needed_from = 4, @@ -92,7 +82,6 @@ struct gconv_fcts __wcsmbs_gconv_fcts = .tomb_nsteps = 1 }; -#if 0 static inline struct __gconv_step * getfct (const char *to, const char *from, size_t *nstepsp) @@ -308,6 +297,5 @@ free_mem (void) } } -#endif text_set_element (__libc_subfreeres, free_mem);