added some tsearch and iconv functions,
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22533 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
b54f4b2da3
commit
87e239b9dc
|
@ -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
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -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
|
||||
;
|
|
@ -23,7 +23,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
//#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,9 +35,8 @@
|
|||
#include <bits/libc-lock.h>
|
||||
#include <gconv_int.h>
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
02111-1307 USA. */
|
||||
|
||||
#include <limits.h>
|
||||
#include <search.h>
|
||||
//#include <search.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -29,6 +29,8 @@
|
|||
#include <gconv_int.h>
|
||||
#include <gconv_charset.h>
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 <drepper@cygnus.com>, 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 <iconv/loop.c>
|
||||
|
@ -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 <iconv/loop.c>
|
||||
|
@ -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; \
|
||||
} \
|
||||
}
|
||||
|
|
|
@ -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 <bits/byteswap.h> directly; include <byteswap.h> 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 */
|
|
@ -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); \
|
||||
|
|
|
@ -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 <bits/string.h> directly; include <string.h> 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 */
|
|
@ -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 <bits/stat.h> directly; use <sys/stat.h> instead."
|
||||
#endif
|
||||
|
||||
/* This structure needs to be defined in accordance with the
|
||||
implementation of __stat, __fstat, and __lstat. */
|
||||
|
||||
#include <bits/types.h>
|
||||
|
||||
#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
|
|
@ -0,0 +1 @@
|
|||
#include <string/byteswap.h>
|
|
@ -1,5 +1,7 @@
|
|||
#ifndef _FCNTL_H
|
||||
|
||||
#include_next <fcntl.h>
|
||||
#include <features.h>
|
||||
|
||||
/* Now define the internal interfaces. */
|
||||
extern int __open64 (__const char *__file, int __oflag, ...);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _SEARCH_H
|
||||
#include <misc/search.h>
|
||||
|
||||
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
|
|
@ -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 */
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef _SYS_STAT_H
|
||||
#include_next <sys/stat.h>
|
||||
#define _SYS_STAT_H 1
|
||||
#define _STAT_VER 0
|
||||
#include <bits/stat.h>
|
||||
|
||||
/* 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
|
|
@ -22,4 +22,7 @@
|
|||
#define __unlink(buf) \
|
||||
unlink(buf)
|
||||
|
||||
#define __getcwd(buf, size) \
|
||||
getcwd(buf, size)
|
||||
|
||||
#endif /* _LIBC_UNISTD_H */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <stdio_ext.h>
|
||||
|
||||
#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)
|
|
@ -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
|
||||
;
|
||||
|
|
|
@ -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
|
||||
;
|
|
@ -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 <features.h>
|
||||
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
|
||||
__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 */
|
|
@ -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 <crux@Pool.Informatik.RWTH-Aachen.DE>, 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <search.h>
|
||||
|
||||
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 <assert.h>
|
||||
|
||||
#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)
|
|
@ -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 ;
|
||||
|
|
|
@ -28,16 +28,6 @@
|
|||
#include <bits/libc-lock.h>
|
||||
#include <iconv/gconv_int.h>
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue