OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/linux/uClibc/libc/string
    from Rev 1325 to Rev 1765
    Reverse comparison

Rev 1325 → Rev 1765

/arm/memcmp.S
0,0 → 1,57
/*
* Copyright (c) 2002 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD memcmp.S, version 1.2 2003/04/05
* by Erik Andersen <andersen@codepoet.org>
*/
 
 
.text
.global memcmp;
.type memcmp,%function
.align 4; \
 
memcmp:
/* if ((len - 1) < 0) return 0 */
subs r2, r2, #1
movmi r0, #0
movmi pc, lr
 
/* ip == last src address to compare */
add ip, r0, r2
1:
ldrb r2, [r0], #1
ldrb r3, [r1], #1
cmp ip, r0
cmpcs r2, r3
beq 1b
sub r0, r2, r3
mov pc, lr
 
.weak bcmp;
bcmp = memcmp
 
/arm/bzero.S
0,0 → 1,48
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Neil A. Carson and Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD bzero.S,v 1.2 1997/10/09
* by Erik Andersen <andersen@codepoet.org>
*/
 
.text
.global bzero;
.type bzero,%function
.align 4; \
 
bzero:
mov r2, r1
mov r1, #0
b memset (PLT)
/arm/memmove.S
0,0 → 1,48
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Neil A. Carson and Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD memmove.S,v 1.3 2003/04/05
* by Erik Andersen <andersen@codepoet.org>
*/
 
.text
.global memmove;
.type memmove,%function
.align 4; \
 
memmove:
stmfd sp!, {r0, lr}
bl _memcpy (PLT)
ldmfd sp!, {r0, pc}
/arm/strncmp.S
0,0 → 1,53
/*
* Copyright (c) 2002 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD strncmp.S, version 1.2 2003/04/05
* by Erik Andersen <andersen@codepoet.org>
*/
 
.text
.global strncmp;
.type strncmp,%function
.align 4; \
 
strncmp:
/* if ((len - 1) < 0) return 0 */
subs r2, r2, #1
movmi r0, #0
movmi pc, lr
 
/* ip == last src address to compare */
add ip, r0, r2
1:
ldrb r2, [r0], #1
ldrb r3, [r1], #1
cmp ip, r0
cmpcs r2, #1
cmpcs r2, r3
beq 1b
sub r0, r2, r3
mov pc, lr
/arm/strlen.S
0,0 → 1,71
/* Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Code contributed by Matthew Wilcox <willy@odie.barnet.ac.uk>
 
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU 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 <endian.h>
#include <sys/syscall.h>
 
/* size_t strlen(const char *S)
* entry: r0 -> string
* exit: r0 = len
*/
 
.text
.global strlen;
.type strlen,%function
.align 4; \
 
strlen:
bic r1, r0, $3 @ addr of word containing first byte
ldr r2, [r1], $4 @ get the first word
ands r3, r0, $3 @ how many bytes are duff?
rsb r0, r3, $0 @ get - that number into counter.
beq Laligned @ skip into main check routine if no
@ more
#if __BYTE_ORDER == __BIG_ENDIAN
orr r2, r2, $0xff000000 @ set this byte to non-zero
subs r3, r3, $1 @ any more to do?
orrgt r2, r2, $0x00ff0000 @ if so, set this byte
subs r3, r3, $1 @ more?
orrgt r2, r2, $0x0000ff00 @ then set.
#else
orr r2, r2, $0x000000ff @ set this byte to non-zero
subs r3, r3, $1 @ any more to do?
orrgt r2, r2, $0x0000ff00 @ if so, set this byte
subs r3, r3, $1 @ more?
orrgt r2, r2, $0x00ff0000 @ then set.
#endif
Laligned: @ here, we have a word in r2. Does it
tst r2, $0x000000ff @ contain any zeroes?
tstne r2, $0x0000ff00 @
tstne r2, $0x00ff0000 @
tstne r2, $0xff000000 @
addne r0, r0, $4 @ if not, the string is 4 bytes longer
ldrne r2, [r1], $4 @ and we continue to the next word
bne Laligned @
Llastword: @ drop through to here once we find a
tst r2, $0x000000ff @ word that has a zero byte in it
addne r0, r0, $1 @
tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it
addne r0, r0, $1 @
tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th
addne r0, r0, $1 @ must be zero)
mov pc,lr
 
.size strlen,.-strlen;
 
/arm/strcmp.S
0,0 → 1,49
/*
* Copyright (c) 2002 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD strcmp.S, version 1.3 2003/04/05
* by Erik Andersen <andersen@codepoet.org>
*/
 
.text
.global strcmp;
.type strcmp,%function
.align 4; \
 
strcmp:
1:
ldrb r2, [r0], #1
ldrb r3, [r1], #1
cmp r2, #1
cmpcs r2, r3
beq 1b
sub r0, r2, r3
mov pc, lr
 
.weak strcoll;
strcoll = strcmp
 
/arm/_memcpy.S
0,0 → 1,583
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Neil A. Carson and Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD _memcpy.S,v 1.6 2003/10/09
* by Erik Andersen <andersen@codepoet.org>
*/
 
 
#include <endian.h>
 
/*
* This is one fun bit of code ...
* Some easy listening music is suggested while trying to understand this
* code e.g. Iron Maiden
*
* For anyone attempting to understand it :
*
* The core code is implemented here with simple stubs for memcpy()
* memmove() and bcopy().
*
* All local labels are prefixed with Lmemcpy_
* Following the prefix a label starting f is used in the forward copy code
* while a label using b is used in the backwards copy code
* The source and destination addresses determine whether a forward or
* backward copy is performed.
* Separate bits of code are used to deal with the following situations
* for both the forward and backwards copy.
* unaligned source address
* unaligned destination address
* Separate copy routines are used to produce an optimised result for each
* of these cases.
* The copy code will use LDM/STM instructions to copy up to 32 bytes at
* a time where possible.
*
* Note: r12 (aka ip) can be trashed during the function along with
* r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
* Additional registers are preserved prior to use i.e. r4, r5 & lr
*
* Apologies for the state of the comments ;-)
*/
 
.text
.global _memcpy;
.type _memcpy,%function
.align 4; \
 
_memcpy:
/* Determine copy direction */
cmp r1, r0
bcc .Lmemcpy_backwards
 
moveq r0, #0 /* Quick abort for len=0 */
moveq pc, lr
 
stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
subs r2, r2, #4
blt .Lmemcpy_fl4 /* less than 4 bytes */
ands r12, r0, #3
bne .Lmemcpy_fdestul /* oh unaligned destination addr */
ands r12, r1, #3
bne .Lmemcpy_fsrcul /* oh unaligned source addr */
 
.Lmemcpy_ft8:
/* We have aligned source and destination */
subs r2, r2, #8
blt .Lmemcpy_fl12 /* less than 12 bytes (4 from above) */
subs r2, r2, #0x14
blt .Lmemcpy_fl32 /* less than 32 bytes (12 from above) */
stmdb sp!, {r4} /* borrow r4 */
 
/* blat 32 bytes at a time */
/* XXX for really big copies perhaps we should use more registers */
.Lmemcpy_floop32:
ldmia r1!, {r3, r4, r12, lr}
stmia r0!, {r3, r4, r12, lr}
ldmia r1!, {r3, r4, r12, lr}
stmia r0!, {r3, r4, r12, lr}
subs r2, r2, #0x20
bge .Lmemcpy_floop32
 
cmn r2, #0x10
ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
stmgeia r0!, {r3, r4, r12, lr}
subge r2, r2, #0x10
ldmia sp!, {r4} /* return r4 */
 
.Lmemcpy_fl32:
adds r2, r2, #0x14
 
/* blat 12 bytes at a time */
.Lmemcpy_floop12:
ldmgeia r1!, {r3, r12, lr}
stmgeia r0!, {r3, r12, lr}
subges r2, r2, #0x0c
bge .Lmemcpy_floop12
 
.Lmemcpy_fl12:
adds r2, r2, #8
blt .Lmemcpy_fl4
 
subs r2, r2, #4
ldrlt r3, [r1], #4
strlt r3, [r0], #4
ldmgeia r1!, {r3, r12}
stmgeia r0!, {r3, r12}
subge r2, r2, #4
 
.Lmemcpy_fl4:
/* less than 4 bytes to go */
adds r2, r2, #4
ldmeqia sp!, {r0, pc} /* done */
 
/* copy the crud byte at a time */
cmp r2, #2
ldrb r3, [r1], #1
strb r3, [r0], #1
ldrgeb r3, [r1], #1
strgeb r3, [r0], #1
ldrgtb r3, [r1], #1
strgtb r3, [r0], #1
ldmia sp!, {r0, pc}
 
/* erg - unaligned destination */
.Lmemcpy_fdestul:
rsb r12, r12, #4
cmp r12, #2
 
/* align destination with byte copies */
ldrb r3, [r1], #1
strb r3, [r0], #1
ldrgeb r3, [r1], #1
strgeb r3, [r0], #1
ldrgtb r3, [r1], #1
strgtb r3, [r0], #1
subs r2, r2, r12
blt .Lmemcpy_fl4 /* less the 4 bytes */
 
ands r12, r1, #3
beq .Lmemcpy_ft8 /* we have an aligned source */
 
/* erg - unaligned source */
/* This is where it gets nasty ... */
.Lmemcpy_fsrcul:
bic r1, r1, #3
ldr lr, [r1], #4
cmp r12, #2
bgt .Lmemcpy_fsrcul3
beq .Lmemcpy_fsrcul2
cmp r2, #0x0c
blt .Lmemcpy_fsrcul1loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5}
 
.Lmemcpy_fsrcul1loop16:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r3, lr, lsl #8
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsr #24
mov r4, r4, lsl #8
orr r4, r4, r5, lsr #24
mov r5, r5, lsl #8
orr r5, r5, r12, lsr #24
mov r12, r12, lsl #8
orr r12, r12, lr, lsr #24
#else
mov r3, lr, lsr #8
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsl #24
mov r4, r4, lsr #8
orr r4, r4, r5, lsl #24
mov r5, r5, lsr #8
orr r5, r5, r12, lsl #24
mov r12, r12, lsr #8
orr r12, r12, lr, lsl #24
#endif
stmia r0!, {r3-r5, r12}
subs r2, r2, #0x10
bge .Lmemcpy_fsrcul1loop16
ldmia sp!, {r4, r5}
adds r2, r2, #0x0c
blt .Lmemcpy_fsrcul1l4
 
.Lmemcpy_fsrcul1loop4:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r12, lr, lsl #8
ldr lr, [r1], #4
orr r12, r12, lr, lsr #24
#else
mov r12, lr, lsr #8
ldr lr, [r1], #4
orr r12, r12, lr, lsl #24
#endif
str r12, [r0], #4
subs r2, r2, #4
bge .Lmemcpy_fsrcul1loop4
 
.Lmemcpy_fsrcul1l4:
sub r1, r1, #3
b .Lmemcpy_fl4
 
.Lmemcpy_fsrcul2:
cmp r2, #0x0c
blt .Lmemcpy_fsrcul2loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5}
 
.Lmemcpy_fsrcul2loop16:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r3, lr, lsl #16
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsr #16
mov r4, r4, lsl #16
orr r4, r4, r5, lsr #16
mov r5, r5, lsl #16
orr r5, r5, r12, lsr #16
mov r12, r12, lsl #16
orr r12, r12, lr, lsr #16
#else
mov r3, lr, lsr #16
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsl #16
mov r4, r4, lsr #16
orr r4, r4, r5, lsl #16
mov r5, r5, lsr #16
orr r5, r5, r12, lsl #16
mov r12, r12, lsr #16
orr r12, r12, lr, lsl #16
#endif
stmia r0!, {r3-r5, r12}
subs r2, r2, #0x10
bge .Lmemcpy_fsrcul2loop16
ldmia sp!, {r4, r5}
adds r2, r2, #0x0c
blt .Lmemcpy_fsrcul2l4
 
.Lmemcpy_fsrcul2loop4:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r12, lr, lsl #16
ldr lr, [r1], #4
orr r12, r12, lr, lsr #16
#else
mov r12, lr, lsr #16
ldr lr, [r1], #4
orr r12, r12, lr, lsl #16
#endif
str r12, [r0], #4
subs r2, r2, #4
bge .Lmemcpy_fsrcul2loop4
 
.Lmemcpy_fsrcul2l4:
sub r1, r1, #2
b .Lmemcpy_fl4
 
.Lmemcpy_fsrcul3:
cmp r2, #0x0c
blt .Lmemcpy_fsrcul3loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5}
 
.Lmemcpy_fsrcul3loop16:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r3, lr, lsl #24
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsr #8
mov r4, r4, lsl #24
orr r4, r4, r5, lsr #8
mov r5, r5, lsl #24
orr r5, r5, r12, lsr #8
mov r12, r12, lsl #24
orr r12, r12, lr, lsr #8
#else
mov r3, lr, lsr #24
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsl #8
mov r4, r4, lsr #24
orr r4, r4, r5, lsl #8
mov r5, r5, lsr #24
orr r5, r5, r12, lsl #8
mov r12, r12, lsr #24
orr r12, r12, lr, lsl #8
#endif
stmia r0!, {r3-r5, r12}
subs r2, r2, #0x10
bge .Lmemcpy_fsrcul3loop16
ldmia sp!, {r4, r5}
adds r2, r2, #0x0c
blt .Lmemcpy_fsrcul3l4
 
.Lmemcpy_fsrcul3loop4:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r12, lr, lsl #24
ldr lr, [r1], #4
orr r12, r12, lr, lsr #8
#else
mov r12, lr, lsr #24
ldr lr, [r1], #4
orr r12, r12, lr, lsl #8
#endif
str r12, [r0], #4
subs r2, r2, #4
bge .Lmemcpy_fsrcul3loop4
 
.Lmemcpy_fsrcul3l4:
sub r1, r1, #1
b .Lmemcpy_fl4
 
.Lmemcpy_backwards:
add r1, r1, r2
add r0, r0, r2
subs r2, r2, #4
blt .Lmemcpy_bl4 /* less than 4 bytes */
ands r12, r0, #3
bne .Lmemcpy_bdestul /* oh unaligned destination addr */
ands r12, r1, #3
bne .Lmemcpy_bsrcul /* oh unaligned source addr */
 
.Lmemcpy_bt8:
/* We have aligned source and destination */
subs r2, r2, #8
blt .Lmemcpy_bl12 /* less than 12 bytes (4 from above) */
stmdb sp!, {r4, lr}
subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */
blt .Lmemcpy_bl32
 
/* blat 32 bytes at a time */
/* XXX for really big copies perhaps we should use more registers */
.Lmemcpy_bloop32:
ldmdb r1!, {r3, r4, r12, lr}
stmdb r0!, {r3, r4, r12, lr}
ldmdb r1!, {r3, r4, r12, lr}
stmdb r0!, {r3, r4, r12, lr}
subs r2, r2, #0x20
bge .Lmemcpy_bloop32
 
.Lmemcpy_bl32:
cmn r2, #0x10
ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
stmgedb r0!, {r3, r4, r12, lr}
subge r2, r2, #0x10
adds r2, r2, #0x14
ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
stmgedb r0!, {r3, r12, lr}
subge r2, r2, #0x0c
ldmia sp!, {r4, lr}
 
.Lmemcpy_bl12:
adds r2, r2, #8
blt .Lmemcpy_bl4
subs r2, r2, #4
ldrlt r3, [r1, #-4]!
strlt r3, [r0, #-4]!
ldmgedb r1!, {r3, r12}
stmgedb r0!, {r3, r12}
subge r2, r2, #4
 
.Lmemcpy_bl4:
/* less than 4 bytes to go */
adds r2, r2, #4
moveq pc, lr /* done */
 
/* copy the crud byte at a time */
cmp r2, #2
ldrb r3, [r1, #-1]!
strb r3, [r0, #-1]!
ldrgeb r3, [r1, #-1]!
strgeb r3, [r0, #-1]!
ldrgtb r3, [r1, #-1]!
strgtb r3, [r0, #-1]!
mov pc, lr
 
/* erg - unaligned destination */
.Lmemcpy_bdestul:
cmp r12, #2
 
/* align destination with byte copies */
ldrb r3, [r1, #-1]!
strb r3, [r0, #-1]!
ldrgeb r3, [r1, #-1]!
strgeb r3, [r0, #-1]!
ldrgtb r3, [r1, #-1]!
strgtb r3, [r0, #-1]!
subs r2, r2, r12
blt .Lmemcpy_bl4 /* less than 4 bytes to go */
ands r12, r1, #3
beq .Lmemcpy_bt8 /* we have an aligned source */
 
/* erg - unaligned source */
/* This is where it gets nasty ... */
.Lmemcpy_bsrcul:
bic r1, r1, #3
ldr r3, [r1, #0]
cmp r12, #2
blt .Lmemcpy_bsrcul1
beq .Lmemcpy_bsrcul2
cmp r2, #0x0c
blt .Lmemcpy_bsrcul3loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5, lr}
 
.Lmemcpy_bsrcul3loop16:
#if __BYTE_ORDER == __BIG_ENDIAN
mov lr, r3, lsr #8
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsl #24
mov r12, r12, lsr #8
orr r12, r12, r5, lsl #24
mov r5, r5, lsr #8
orr r5, r5, r4, lsl #24
mov r4, r4, lsr #8
orr r4, r4, r3, lsl #24
#else
mov lr, r3, lsl #8
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsr #24
mov r12, r12, lsl #8
orr r12, r12, r5, lsr #24
mov r5, r5, lsl #8
orr r5, r5, r4, lsr #24
mov r4, r4, lsl #8
orr r4, r4, r3, lsr #24
#endif
stmdb r0!, {r4, r5, r12, lr}
subs r2, r2, #0x10
bge .Lmemcpy_bsrcul3loop16
ldmia sp!, {r4, r5, lr}
adds r2, r2, #0x0c
blt .Lmemcpy_bsrcul3l4
 
.Lmemcpy_bsrcul3loop4:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r12, r3, lsr #8
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsl #24
#else
mov r12, r3, lsl #8
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsr #24
#endif
str r12, [r0, #-4]!
subs r2, r2, #4
bge .Lmemcpy_bsrcul3loop4
 
.Lmemcpy_bsrcul3l4:
add r1, r1, #3
b .Lmemcpy_bl4
 
.Lmemcpy_bsrcul2:
cmp r2, #0x0c
blt .Lmemcpy_bsrcul2loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5, lr}
 
.Lmemcpy_bsrcul2loop16:
#if __BYTE_ORDER == __BIG_ENDIAN
mov lr, r3, lsr #16
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsl #16
mov r12, r12, lsr #16
orr r12, r12, r5, lsl #16
mov r5, r5, lsr #16
orr r5, r5, r4, lsl #16
mov r4, r4, lsr #16
orr r4, r4, r3, lsl #16
#else
mov lr, r3, lsl #16
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsr #16
mov r12, r12, lsl #16
orr r12, r12, r5, lsr #16
mov r5, r5, lsl #16
orr r5, r5, r4, lsr #16
mov r4, r4, lsl #16
orr r4, r4, r3, lsr #16
#endif
stmdb r0!, {r4, r5, r12, lr}
subs r2, r2, #0x10
bge .Lmemcpy_bsrcul2loop16
ldmia sp!, {r4, r5, lr}
adds r2, r2, #0x0c
blt .Lmemcpy_bsrcul2l4
 
.Lmemcpy_bsrcul2loop4:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r12, r3, lsr #16
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsl #16
#else
mov r12, r3, lsl #16
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsr #16
#endif
str r12, [r0, #-4]!
subs r2, r2, #4
bge .Lmemcpy_bsrcul2loop4
 
.Lmemcpy_bsrcul2l4:
add r1, r1, #2
b .Lmemcpy_bl4
 
.Lmemcpy_bsrcul1:
cmp r2, #0x0c
blt .Lmemcpy_bsrcul1loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5, lr}
 
.Lmemcpy_bsrcul1loop32:
#if __BYTE_ORDER == __BIG_ENDIAN
mov lr, r3, lsr #24
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsl #8
mov r12, r12, lsr #24
orr r12, r12, r5, lsl #8
mov r5, r5, lsr #24
orr r5, r5, r4, lsl #8
mov r4, r4, lsr #24
orr r4, r4, r3, lsl #8
#else
mov lr, r3, lsl #24
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsr #8
mov r12, r12, lsl #24
orr r12, r12, r5, lsr #8
mov r5, r5, lsl #24
orr r5, r5, r4, lsr #8
mov r4, r4, lsl #24
orr r4, r4, r3, lsr #8
#endif
stmdb r0!, {r4, r5, r12, lr}
subs r2, r2, #0x10
bge .Lmemcpy_bsrcul1loop32
ldmia sp!, {r4, r5, lr}
adds r2, r2, #0x0c
blt .Lmemcpy_bsrcul1l4
 
.Lmemcpy_bsrcul1loop4:
#if __BYTE_ORDER == __BIG_ENDIAN
mov r12, r3, lsr #24
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsl #8
#else
mov r12, r3, lsl #24
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsr #8
#endif
str r12, [r0, #-4]!
subs r2, r2, #4
bge .Lmemcpy_bsrcul1loop4
 
.Lmemcpy_bsrcul1l4:
add r1, r1, #1
b .Lmemcpy_bl4
/arm/memcpy.S
0,0 → 1,48
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Neil A. Carson and Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD memcpy.S,v 1.3 2003/04/05
* by Erik Andersen <andersen@codepoet.org>
*/
 
.text
.global memcpy;
.type memcpy,%function
.align 4; \
 
memcpy:
stmfd sp!, {r0, lr}
bl _memcpy (PLT)
ldmfd sp!, {r0, pc}
/arm/memset.S
0,0 → 1,72
/* Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Philip Blundell <philb@gnu.org>
 
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 <sys/syscall.h>
 
.text
.global memset;
.type memset,%function
.align 4; \
 
memset:
mov a4, a1
cmp a3, $8 @ at least 8 bytes to do?
blt 2f
orr a2, a2, a2, lsl $8
orr a2, a2, a2, lsl $16
1:
tst a4, $3 @ aligned yet?
strneb a2, [a4], $1
subne a3, a3, $1
bne 1b
mov ip, a2
1:
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
blt 2f
stmia a4!, {a2, ip}
sub a3, a3, $8
cmp a3, $8 @ 8 bytes still to do?
stmgeia a4!, {a2, ip}
subge a3, a3, $8
bge 1b
2:
movs a3, a3 @ anything left?
moveq pc, lr @ nope
rsb a3, a3, $7
add pc, pc, a3, lsl $2
mov r0, r0
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
strb a2, [a4], $1
mov pc, lr
 
.size memset,.-memset;
 
/arm/Makefile
0,0 → 1,39
# Makefile for uClibc
#
# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
# details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
TOPDIR=../../../
include $(TOPDIR)Rules.mak
 
SSRC= _memcpy.S bcopy.S bzero.S memcmp.S memcpy.S memmove.S memset.S \
strcmp.S strlen.S strncmp.S
SOBJS=$(patsubst %.S,%.o, $(SSRC))
 
all: $(SOBJS) $(LIBC)
 
$(LIBC): ar-target
 
ar-target: $(SOBJS)
$(AR) $(ARFLAGS) $(LIBC) $(SOBJS)
 
$(SOBJS): %.o : %.S
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
clean:
$(RM) *.[oa] *~ core
 
/arm/bcopy.S
0,0 → 1,52
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Neil A. Carson and Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Adapted for uClibc from NetBSD bcopy.S,v 1.2 1997/10/09
* by Erik Andersen <andersen@codepoet.org>
*/
 
/* bcopy = memcpy/memmove with arguments reversed. */
 
.text
.global bcopy;
.type bcopy,%function
.align 4; \
 
bcopy:
/* switch the source and destination registers */
eor r0, r1, r0
eor r1, r0, r1
eor r0, r1, r0
b _memcpy (PLT)
/sh64/strcpy.S
0,0 → 1,98
/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */
/* Modified by SuperH, Inc. September 2003 */
! Entry: arg0: destination
! arg1: source
! Exit: result: destination
!
! SH5 code Copyright 2002 SuperH Ltd.
 
#ifdef __LITTLE_ENDIAN__
#define SHHI shlld
#define SHLO shlrd
#else
#define SHHI shlrd
#define SHLO shlld
#endif
 
.section .text..SHmedia32,"ax"
.globl strcpy
.type strcpy, @function
 
.align 5
strcpy:
 
pta/l shortstring,tr1
ldlo.q r3,0,r4
ptabs r18,tr4
shlli r3,3,r7
addi r2, 8, r0
mcmpeq.b r4,r63,r6
SHHI r6,r7,r6
bnei/u r6,0,tr1 // shortstring
pta/l no_lddst, tr2
ori r3,-8,r23
sub r2, r23, r0
sub r3, r2, r21
addi r21, 8, r20
ldx.q r0, r21, r5
pta/l loop, tr0
ori r2,-8,r22
mcmpeq.b r5, r63, r6
bgt/u r22, r23, tr2 // no_lddst
 
// r22 < r23 : Need to do a load from the destination.
// r22 == r23 : Doesn't actually need to load from destination,
// but still can be handled here.
ldlo.q r2, 0, r9
movi -1, r8
SHLO r8, r7, r8
mcmv r4, r8, r9
stlo.q r2, 0, r9
beqi/l r6, 0, tr0 // loop
 
add r5, r63, r4
addi r0, 8, r0
blink tr1, r63 // shortstring
no_lddst:
// r22 > r23: note that for r22 == r23 the sthi.q would clobber
// bytes before the destination region.
stlo.q r2, 0, r4
SHHI r4, r7, r4
sthi.q r0, -1, r4
beqi/l r6, 0, tr0 // loop
 
add r5, r63, r4
addi r0, 8, r0
shortstring:
#ifndef __LITTLE_ENDIAN__
pta/l shortstring2,tr1
byterev r4,r4
#endif
shortstring2:
st.b r0,-8,r4
andi r4,0xff,r5
shlri r4,8,r4
addi r0,1,r0
bnei/l r5,0,tr1
blink tr4,r63 // return
.balign 8
loop:
stlo.q r0, 0, r5
ldx.q r0, r20, r4
addi r0, 16, r0
sthi.q r0, -9, r5
mcmpeq.b r4, r63, r6
bnei/u r6, 0, tr1 // shortstring
ldx.q r0, r21, r5
stlo.q r0, -8, r4
sthi.q r0, -1, r4
mcmpeq.b r5, r63, r6
beqi/l r6, 0, tr0 // loop
 
add r5, r63, r4
addi r0, 8, r0
blink tr1, r63 // shortstring
 
.size strcpy, . - strcpy
 
/sh64/memcpy.S
0,0 → 1,202
/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */
/* Modified by SuperH, Inc. September 2003 */
!
! Fast SH memcpy
!
! by Toshiyasu Morita (tm@netcom.com)
! hacked by J"orn Rernnecke (joern.rennecke@superh.com) ("o for o-umlaut)
! SH5 code Copyright 2002 SuperH Ltd.
!
! Entry: ARG0: destination pointer
! ARG1: source pointer
! ARG2: byte count
!
! Exit: RESULT: destination pointer
! any other registers in the range r0-r7: trashed
!
! Notes: Usually one wants to do small reads and write a longword, but
! unfortunately it is difficult in some cases to concatanate bytes
! into a longword on the SH, so this does a longword read and small
! writes.
!
! This implementation makes two assumptions about how it is called:
!
! 1.: If the byte count is nonzero, the address of the last byte to be
! copied is unsigned greater than the address of the first byte to
! be copied. This could be easily swapped for a signed comparison,
! but the algorithm used needs some comparison.
!
! 2.: When there are two or three bytes in the last word of an 11-or-more
! bytes memory chunk to b copied, the rest of the word can be read
! without side effects.
! This could be easily changed by increasing the minumum size of
! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2,
! however, this would cost a few extra cyles on average.
! For SHmedia, the assumption is that any quadword can be read in its
! enirety if at least one byte is included in the copy.
!
 
.section .text..SHmedia32,"ax"
.globl memcpy
.type memcpy, @function
 
.align 5
memcpy:
 
#define LDUAQ(P,O,D0,D1) ldlo.q P,O,D0; ldhi.q P,O+7,D1
#define STUAQ(P,O,D0,D1) stlo.q P,O,D0; sthi.q P,O+7,D1
#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1
#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1
 
ld.b r3,0,r63
pta/l Large,tr0
movi 25,r0
bgeu/u r4,r0,tr0
nsb r4,r0
shlli r0,5,r0
movi (L1-L0+63*32 + 1) & 0xffff,r1
sub r1, r0, r0
L0: ptrel r0,tr0
add r2,r4,r5
ptabs r18,tr1
add r3,r4,r6
blink tr0,r63
/* Rearranged to make cut2 safe */
.balign 8
L4_7: /* 4..7 byte memcpy cntd. */
stlo.l r2, 0, r0
or r6, r7, r6
sthi.l r5, -1, r6
stlo.l r5, -4, r6
blink tr1,r63
 
.balign 8
L1: /* 0 byte memcpy */
nop
blink tr1,r63
nop
nop
nop
nop
 
L2_3: /* 2 or 3 byte memcpy cntd. */
st.b r5,-1,r6
blink tr1,r63
 
/* 1 byte memcpy */
ld.b r3,0,r0
st.b r2,0,r0
blink tr1,r63
 
L8_15: /* 8..15 byte memcpy cntd. */
stlo.q r2, 0, r0
or r6, r7, r6
sthi.q r5, -1, r6
stlo.q r5, -8, r6
blink tr1,r63
/* 2 or 3 byte memcpy */
ld.b r3,0,r0
ld.b r2,0,r63
ld.b r3,1,r1
st.b r2,0,r0
pta/l L2_3,tr0
ld.b r6,-1,r6
st.b r2,1,r1
blink tr0, r63
 
/* 4 .. 7 byte memcpy */
LDUAL (r3, 0, r0, r1)
pta L4_7, tr0
ldlo.l r6, -4, r7
or r0, r1, r0
sthi.l r2, 3, r0
ldhi.l r6, -1, r6
blink tr0, r63
 
/* 8 .. 15 byte memcpy */
LDUAQ (r3, 0, r0, r1)
pta L8_15, tr0
ldlo.q r6, -8, r7
or r0, r1, r0
sthi.q r2, 7, r0
ldhi.q r6, -1, r6
blink tr0, r63
 
/* 16 .. 24 byte memcpy */
LDUAQ (r3, 0, r0, r1)
LDUAQ (r3, 8, r8, r9)
or r0, r1, r0
sthi.q r2, 7, r0
or r8, r9, r8
sthi.q r2, 15, r8
ldlo.q r6, -8, r7
ldhi.q r6, -1, r6
stlo.q r2, 8, r8
stlo.q r2, 0, r0
or r6, r7, r6
sthi.q r5, -1, r6
stlo.q r5, -8, r6
blink tr1,r63
 
Large:
ld.b r2, 0, r63
pta/l Loop_ua, tr1
ori r3, -8, r7
sub r2, r7, r22
sub r3, r2, r6
add r2, r4, r5
ldlo.q r3, 0, r0
addi r5, -16, r5
movi 64+8, r27 // could subtract r7 from that.
stlo.q r2, 0, r0
sthi.q r2, 7, r0
ldx.q r22, r6, r0
bgtu/l r27, r4, tr1
 
addi r5, -48, r27
pta/l Loop_line, tr0
addi r6, 64, r36
addi r6, -24, r19
addi r6, -16, r20
addi r6, -8, r21
 
Loop_line:
ldx.q r22, r36, r63
alloco r22, 32
addi r22, 32, r22
ldx.q r22, r19, r23
sthi.q r22, -25, r0
ldx.q r22, r20, r24
ldx.q r22, r21, r25
stlo.q r22, -32, r0
ldx.q r22, r6, r0
sthi.q r22, -17, r23
sthi.q r22, -9, r24
sthi.q r22, -1, r25
stlo.q r22, -24, r23
stlo.q r22, -16, r24
stlo.q r22, -8, r25
bgeu r27, r22, tr0
 
Loop_ua:
addi r22, 8, r22
sthi.q r22, -1, r0
stlo.q r22, -8, r0
ldx.q r22, r6, r0
bgtu/l r5, r22, tr1
 
add r3, r4, r7
ldlo.q r7, -8, r1
sthi.q r22, 7, r0
ldhi.q r7, -1, r7
ptabs r18,tr1
stlo.q r22, 0, r0
or r1, r7, r1
sthi.q r5, 15, r1
stlo.q r5, 8, r1
blink tr1, r63
 
.size memcpy, . - memcpy
 
/sh64/memset.S
0,0 → 1,92
/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */
/* Modified by SuperH, Inc. September 2003 */
!
! Fast SH memset
!
! by Toshiyasu Morita (tm@netcom.com)
!
! SH5 code by J"orn Rennecke (joern.rennecke@superh.com)
! Copyright 2002 SuperH Ltd.
!
 
#ifdef __LITTLE_ENDIAN__
#define SHHI shlld
#define SHLO shlrd
#else
#define SHHI shlrd
#define SHLO shlld
#endif
 
.section .text..SHmedia32,"ax"
.globl memset
.type memset, @function
 
.align 5
 
memset:
pta/l multiquad, tr0
andi r2, 7, r22
ptabs r18, tr2
mshflo.b r3,r3,r3
add r4, r22, r23
mperm.w r3, r63, r3 // Fill pattern now in every byte of r3
 
movi 8, r9
bgtu/u r23, r9, tr0 // multiquad
 
beqi/u r4, 0, tr2 // Return with size 0 - ensures no mem accesses
ldlo.q r2, 0, r7
shlli r4, 2, r4
movi -1, r8
SHHI r8, r4, r8
SHHI r8, r4, r8
mcmv r7, r8, r3
stlo.q r2, 0, r3
blink tr2, r63
 
multiquad:
pta/l lastquad, tr0
stlo.q r2, 0, r3
shlri r23, 3, r24
add r2, r4, r5
beqi/u r24, 1, tr0 // lastquad
pta/l loop, tr1
sub r2, r22, r25
andi r5, -8, r20 // calculate end address and
addi r20, -7*8, r8 // loop end address; This might overflow, so we need
// to use a different test before we start the loop
bge/u r24, r9, tr1 // loop
st.q r25, 8, r3
st.q r20, -8, r3
shlri r24, 1, r24
beqi/u r24, 1, tr0 // lastquad
st.q r25, 16, r3
st.q r20, -16, r3
beqi/u r24, 2, tr0 // lastquad
st.q r25, 24, r3
st.q r20, -24, r3
lastquad:
sthi.q r5, -1, r3
blink tr2,r63
 
loop:
!!! alloco r25, 32 // QQQ comment out for short-term fix to SHUK #3895.
// QQQ commenting out is locically correct, but sub-optimal
// QQQ Sean McGoogan - 4th April 2003.
st.q r25, 8, r3
st.q r25, 16, r3
st.q r25, 24, r3
st.q r25, 32, r3
addi r25, 32, r25
bgeu/l r8, r25, tr1 // loop
 
st.q r20, -40, r3
st.q r20, -32, r3
st.q r20, -24, r3
st.q r20, -16, r3
st.q r20, -8, r3
sthi.q r5, -1, r3
blink tr2,r63
 
.size memset, . - memset
 
/sh64/Makefile
0,0 → 1,38
# Makefile for uClibc's sh64 optimized string routines
#
# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
# details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
TOPDIR=../../../
include $(TOPDIR)Rules.mak
 
SSRC= memcpy.S memset.S strcpy.S
SOBJS=$(patsubst %.S,%.o, $(SSRC))
 
all: $(SOBJS) $(LIBC)
 
$(LIBC): ar-target
 
ar-target: $(SOBJS)
$(AR) $(ARFLAGS) $(LIBC) $(SOBJS)
 
$(SOBJS): %.o : %.S
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
clean:
$(RM) *.[oa] *~ core
 
/i386/string.c
0,0 → 1,322
/*
* This string-include defines all string functions as inline
* functions. Use gcc. It also assumes ds=es=data space, this should be
* normal. Most of the string-functions are rather heavily hand-optimized,
* see especially strtok,strstr,str[c]spn. They should work, but are not
* very easy to understand. Everything is done entirely within the register
* set, making the functions fast and clean. String instructions have been
* used through-out, making for "slightly" unclear code :-)
*
* NO Copyright (C) 1991, 1992 Linus Torvalds,
* consider these trivial functions to be PD.
*
* Modified for uClibc by Erik Andersen <andersen@codepoet.org>
* These make no attempt to use nifty things like mmx/3dnow/etc.
* These are not inline, and will therefore not be as fast as
* modifying the headers to use inlines (and cannot therefore
* do tricky things when dealing with const memory). But they
* should (I hope!) be faster than their generic equivalents....
*
* More importantly, these should provide a good example for
* others to follow when adding arch specific optimizations.
* -Erik
*/
 
#define _STDIO_UTILITY
#define _GNU_SOURCE
#include <string.h>
#include <locale.h> /* for __LOCALE_C_ONLY */
 
#ifdef L_strcpy
char * strcpy(char * dest, const char * src)
{
int d0, d1, d2;
__asm__ __volatile__(
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
:"0" (src),"1" (dest) : "memory");
return dest;
}
#endif
 
 
#ifdef L_strncpy
char * strncpy(char * dest, const char * src, size_t count)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
"1:\tdecl %2\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"rep\n\t"
"stosb\n"
"2:"
: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
:"0" (src),"1" (dest),"2" (count) : "memory");
return dest;
}
#endif
 
 
#ifdef L_strcat
char *strcat(char * dest, const char * src)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
"decl %1\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
: "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
return dest;
}
#endif
 
 
#ifdef L_strncat
char *strncat(char * dest,
const char * src, size_t count)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
"movl %8,%3\n"
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %2,%2\n\t"
"stosb"
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
: "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
: "memory");
return dest;
}
#endif
 
 
#ifdef L_strcmp
int strcmp(const char *cs, const char *ct)
{
int d0, d1;
register int __res;
__asm__ __volatile__(
"1:\tlodsb\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:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"3:"
:"=a" (__res), "=&S" (d0), "=&D" (d1)
:"1" (cs),"2" (ct));
return __res;
}
#ifdef __LOCALE_C_ONLY
weak_alias(strcmp,strcoll);
#endif /* __LOCALE_C_ONLY */
#endif
 
 
#ifdef L_strncmp
int strncmp(const char *cs, const char *ct, size_t count)
{
register int __res;
int d0, d1, d2;
__asm__ __volatile__(
"1:\tdecl %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:\txorl %%eax,%%eax\n\t"
"jmp 4f\n"
"3:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"4:"
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
:"1" (cs),"2" (ct),"3" (count));
return __res;
}
#endif
 
 
#ifdef L_strchr
char * strchr(const char *s, int c)
{
int d0;
register char * __res;
__asm__ __volatile__(
"movb %%al,%%ah\n"
"1:\tlodsb\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:\tmovl %1,%0\n\t"
"decl %0"
:"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
return __res;
}
weak_alias(strchr,index);
#endif
 
 
#ifdef L_strrchr
char *strrchr(const char *s, int c)
{
int d0, d1;
register char * __res;
__asm__ __volatile__(
"movb %%al,%%ah\n"
"1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t"
"jne 2f\n\t"
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
:"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
return __res;
}
weak_alias(strrchr,rindex);
#endif
 
 
 
#ifdef L_strlen
size_t strlen(const char *s)
{
int d0;
register int __res;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
"notl %0\n\t"
"decl %0"
:"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
return __res;
}
#endif
 
 
#ifdef L_strnlen
size_t strnlen(const char *s, size_t count)
{
int d0;
register int __res;
__asm__ __volatile__(
"movl %2,%0\n\t"
"jmp 2f\n"
"1:\tcmpb $0,(%0)\n\t"
"je 3f\n\t"
"incl %0\n"
"2:\tdecl %1\n\t"
"cmpl $-1,%1\n\t"
"jne 1b\n"
"3:\tsubl %2,%0"
:"=a" (__res), "=&d" (d0)
:"c" (s),"1" (count));
return __res;
}
#endif
 
 
#ifdef L_memcpy
void *memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
: "memory");
return (to);
}
#endif
 
 
#ifdef L_memmove
void *memmove(void *dest, const void *src, size_t n)
{
int d0, d1, d2;
if (dest<src)
__asm__ __volatile__(
"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
 
#ifdef L_memchr
void *memchr(const void *cs, int c, size_t count)
{
int d0;
register void * __res;
if (!count)
return NULL;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
:"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
return __res;
}
#endif
 
#ifdef L_memset
void *memset(void *s, int c, size_t count)
{
int d0, d1;
__asm__ __volatile__(
"rep\n\t"
"stosb"
: "=&c" (d0), "=&D" (d1)
:"a" (c),"1" (s),"0" (count)
:"memory");
return s;
}
#endif
 
/i386/Makefile
0,0 → 1,45
# Makefile for uClibc
#
# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
# details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
TOPDIR=../../../
include $(TOPDIR)Rules.mak
 
MSRC= string.c
MOBJ= strcpy.o strncpy.o strcat.o strncat.o strcmp.o \
strncmp.o strchr.o strrchr.o strlen.o strnlen.o \
memcpy.o memmove.o memchr.o memset.o
OBJS=$(MOBJ)
 
all: $(OBJS) $(LIBC)
 
$(LIBC): ar-target
 
ar-target: $(OBJS)
$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
$(MOBJ): $(MSRC)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(COBJS): %.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
clean:
$(RM) *.[oa] *~ core
 
/Makefile
0,0 → 1,102
# Makefile for uClibc
#
# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Library General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
# details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
TOPDIR=../../
include $(TOPDIR)Rules.mak
 
DIRS=
ifeq ($(TARGET_ARCH),$(wildcard $(TARGET_ARCH)))
DIRS = $(TARGET_ARCH)
endif
ALL_SUBDIRS = i386 arm sh64
 
MSRC= wstring.c
MOBJ= basename.o bcopy.o bzero.o dirname.o ffs.o memccpy.o memchr.o memcmp.o \
memcpy.o memmove.o mempcpy.o memrchr.o memset.o rawmemchr.o stpcpy.o \
stpncpy.o strcasecmp.o strcasestr.o strcat.o strchrnul.o strchr.o \
strcmp.o strcpy.o strcspn.o strdup.o strlen.o strncasecmp.o strncat.o \
strncmp.o strncpy.o strndup.o strnlen.o strpbrk.o strrchr.o strsep.o \
strspn.o strstr.o strtok.o strtok_r.o strerror.o _susv3_strerror_r.o \
_string_syserrmsgs.o _glibc_strerror_r.o \
_string_syssigmsgs.o sys_siglist.o strsignal.o psignal.o \
__xpg_basename.o strlcat.o strlcpy.o sys_errlist.o memmem.o
 
MOBJW= wcscasecmp.o wcscat.o wcschrnul.o wcschr.o wcscmp.o wcscpy.o wcscspn.o \
wcsdup.o wcslen.o wcsncasecmp.o wcsncat.o wcsncmp.o wcsncpy.o \
wcsnlen.o wcspbrk.o wcsrchr.o wcsspn.o wcsstr.o wcstok.o wmemchr.o \
wmemcmp.o wmemcpy.o wmemmove.o wmempcpy.o wmemset.o wcpcpy.o wcpncpy.o \
__wcslcpy.o \
wcsxfrm.o strxfrm.o # wcscoll strcoll.o
 
MOBJx=
MOBJWx=
 
ifeq ($(UCLIBC_HAS_XLOCALE),y)
MOBJx += strcasecmp_l.o strncasecmp_l.o
MOBJWx += wcscasecmp_l.o wcsncasecmp_l.o wcsxfrm_l.o strxfrm_l.o
endif
 
#ffsl ffsll
 
OBJS=$(MOBJ) $(MOBJx)
 
ifeq ($(UCLIBC_HAS_WCHAR),y)
OBJS += $(MOBJW) $(MOBJWx)
endif
 
all: $(LIBC) subdirs
 
$(LIBC): ar-target
 
ar-target: $(OBJS)
$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 
$(MOBJ): $(MSRC)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(MOBJx): $(MSRC)
$(CC) $(CFLAGS) -DL_$* -D__UCLIBC_DO_XLOCALE $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(MOBJW): $(MSRC)
$(CC) $(CFLAGS) -DWANT_WIDE -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(MOBJWx): $(MSRC)
$(CC) $(CFLAGS) -DWANT_WIDE -DL_$* -D__UCLIBC_DO_XLOCALE $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
$(COBJS): %.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
 
clean: subdirs_clean
$(RM) *.[oa] *~ core
 
subdirs: $(patsubst %, _dir_%, $(DIRS))
subdirs_clean: $(patsubst %, _dirclean_%, $(ALL_SUBDIRS))
 
$(patsubst %, _dir_%, $(DIRS)) : $(OBJS)
$(MAKE) -C $(patsubst _dir_%, %, $@)
 
$(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) : dummy
$(MAKE) -C $(patsubst _dirclean_%, %, $@) clean
 
.PHONY: dummy
 
/.indent.pro
0,0 → 1,33
--blank-lines-after-declarations
--blank-lines-after-procedures
--break-before-boolean-operator
--no-blank-lines-after-commas
--braces-on-if-line
--braces-on-struct-decl-line
--comment-indentation25
--declaration-comment-column25
--no-comment-delimiters-on-blank-lines
--cuddle-else
--continuation-indentation4
--case-indentation0
--else-endif-column33
--space-after-cast
--line-comments-indentation0
--declaration-indentation1
--dont-format-first-column-comments
--dont-format-comments
--honour-newlines
--indent-level4
/* changed from 0 to 4 */
--parameter-indentation4
--line-length78 /* changed from 75 */
--continue-at-parentheses
--no-space-after-function-call-names
--dont-break-procedure-type
--dont-star-comments
--leave-optional-blank-lines
--dont-space-special-semicolon
--tab-size4
/* additions by Mark */
--case-brace-indentation0
--leave-preprocessor-space
/wstring.c
0,0 → 1,2987
/* Copyright (C) 2002 Manuel Novoa III
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
*
* Besides uClibc, I'm using this code in my libc for elks, which is
* a 16-bit environment with a fairly limited compiler. It would make
* things much easier for me if this file isn't modified unnecessarily.
* In particular, please put any new or replacement functions somewhere
* else, and modify the makefile to use your version instead.
* Thanks. Manuel
*
* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
 
/* Dec 20, 2002
* Initial test implementation of strcoll, strxfrm, wcscoll, and wcsxfrm.
* The code needs to be cleaned up a good bit, but I'd like to see people
* test it out.
*
* Sep 11, 2003
* Patch by Atsushi Nemoto <anemo@mba.ocn.ne.jp> to do arch-required
* mapping of signal strings (alpha, mips, hppa, sparc).
*/
 
#define _STDIO_UTILITY
#define _GNU_SOURCE
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <locale.h>
 
#ifdef WANT_WIDE
#include <wchar.h>
#include <wctype.h>
#include <bits/uClibc_uwchar.h>
 
#define Wvoid wchar_t
#define Wchar wchar_t
#define Wuchar __uwchar_t
#define Wint wchar_t
 
#else
 
#define Wvoid void
#define Wchar char
typedef unsigned char __string_uchar_t;
#define Wuchar __string_uchar_t
#define Wint int
 
#endif
 
/**********************************************************************/
/* NOTE: If we ever do internationalized syserr messages, this will
* have to be changed! */
 
#define _SYS_NERR 125
#if defined(__mips__) || defined(__sparc__)
/* sparce and mips have an extra error entry, as EDEADLK and EDEADLOCK have
* different meanings on those platforms. */
#undef _SYS_NERR
#define _SYS_NERR 126
#endif
 
#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
#define _SYS_ERRMSG_MAXLEN 50
#else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
#define _SYS_ERRMSG_MAXLEN 0
#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
 
 
extern const char _string_syserrmsgs[];
 
#define _SYS_NSIG 32
 
#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__
#define _SYS_SIGMSG_MAXLEN 25
#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
#define _SYS_SIGMSG_MAXLEN 0
#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
 
extern const char _string_syssigmsgs[];
 
 
#if _SYS_ERRMSG_MAXLEN < __UIM_BUFLEN_INT + 14
#define _STRERROR_BUFSIZE (__UIM_BUFLEN_INT + 14)
#else
#define _STRERROR_BUFSIZE _SYS_ERRMSG_MAXLEN
#endif
 
#if _SYS_SIGMSG_MAXLEN < __UIM_BUFLEN_INT + 15
#define _STRSIGNAL_BUFSIZE (__UIM_BUFLEN_INT + 15)
#else
#define _STRSIGNAL_BUFSIZE _SYS_SIGMSG_MAXLEN
#endif
 
/**********************************************************************/
#if defined(L__string_syserrmsgs) && defined(__UCLIBC_HAS_ERRNO_MESSAGES__)
 
const char _string_syserrmsgs[] = {
/* 0: 0, 8 */ "Success\0"
/* 1: 8, 24 */ "Operation not permitted\0"
/* 2: 32, 26 */ "No such file or directory\0"
/* 3: 58, 16 */ "No such process\0"
/* 4: 74, 24 */ "Interrupted system call\0"
/* 5: 98, 19 */ "Input/output error\0"
/* 6: 117, 26 */ "No such device or address\0"
/* 7: 143, 23 */ "Argument list too long\0"
/* 8: 166, 18 */ "Exec format error\0"
/* 9: 184, 20 */ "Bad file descriptor\0"
/* 10: 204, 19 */ "No child processes\0"
/* 11: 223, 33 */ "Resource temporarily unavailable\0"
/* 12: 256, 23 */ "Cannot allocate memory\0"
/* 13: 279, 18 */ "Permission denied\0"
/* 14: 297, 12 */ "Bad address\0"
/* 15: 309, 22 */ "Block device required\0"
/* 16: 331, 24 */ "Device or resource busy\0"
/* 17: 355, 12 */ "File exists\0"
/* 18: 367, 26 */ "Invalid cross-device link\0"
/* 19: 393, 15 */ "No such device\0"
/* 20: 408, 16 */ "Not a directory\0"
/* 21: 424, 15 */ "Is a directory\0"
/* 22: 439, 17 */ "Invalid argument\0"
/* 23: 456, 30 */ "Too many open files in system\0"
/* 24: 486, 20 */ "Too many open files\0"
/* 25: 506, 31 */ "Inappropriate ioctl for device\0"
/* 26: 537, 15 */ "Text file busy\0"
/* 27: 552, 15 */ "File too large\0"
/* 28: 567, 24 */ "No space left on device\0"
/* 29: 591, 13 */ "Illegal seek\0"
/* 30: 604, 22 */ "Read-only file system\0"
/* 31: 626, 15 */ "Too many links\0"
/* 32: 641, 12 */ "Broken pipe\0"
/* 33: 653, 33 */ "Numerical argument out of domain\0"
/* 34: 686, 30 */ "Numerical result out of range\0"
/* 35: 716, 26 */ "Resource deadlock avoided\0"
/* 36: 742, 19 */ "File name too long\0"
/* 37: 761, 19 */ "No locks available\0"
/* 38: 780, 25 */ "Function not implemented\0"
/* 39: 805, 20 */ "Directory not empty\0"
/* 40: 825, 34 */ "Too many levels of symbolic links\0"
/* 41: 859, 1 */ "\0"
/* 42: 860, 27 */ "No message of desired type\0"
/* 43: 887, 19 */ "Identifier removed\0"
/* 44: 906, 28 */ "Channel number out of range\0"
/* 45: 934, 25 */ "Level 2 not synchronized\0"
/* 46: 959, 15 */ "Level 3 halted\0"
/* 47: 974, 14 */ "Level 3 reset\0"
/* 48: 988, 25 */ "Link number out of range\0"
/* 49: 1013, 29 */ "Protocol driver not attached\0"
/* 50: 1042, 27 */ "No CSI structure available\0"
/* 51: 1069, 15 */ "Level 2 halted\0"
/* 52: 1084, 17 */ "Invalid exchange\0"
/* 53: 1101, 27 */ "Invalid request descriptor\0"
/* 54: 1128, 14 */ "Exchange full\0"
/* 55: 1142, 9 */ "No anode\0"
/* 56: 1151, 21 */ "Invalid request code\0"
/* 57: 1172, 13 */ "Invalid slot\0"
/* 58: 1185, 1 */ "\0"
/* 59: 1186, 21 */ "Bad font file format\0"
/* 60: 1207, 20 */ "Device not a stream\0"
/* 61: 1227, 18 */ "No data available\0"
/* 62: 1245, 14 */ "Timer expired\0"
/* 63: 1259, 25 */ "Out of streams resources\0"
/* 64: 1284, 30 */ "Machine is not on the network\0"
/* 65: 1314, 22 */ "Package not installed\0"
/* 66: 1336, 17 */ "Object is remote\0"
/* 67: 1353, 22 */ "Link has been severed\0"
/* 68: 1375, 16 */ "Advertise error\0"
/* 69: 1391, 14 */ "Srmount error\0"
/* 70: 1405, 28 */ "Communication error on send\0"
/* 71: 1433, 15 */ "Protocol error\0"
/* 72: 1448, 19 */ "Multihop attempted\0"
/* 73: 1467, 19 */ "RFS specific error\0"
/* 74: 1486, 12 */ "Bad message\0"
/* 75: 1498, 38 */ "Value too large for defined data type\0"
/* 76: 1536, 27 */ "Name not unique on network\0"
/* 77: 1563, 29 */ "File descriptor in bad state\0"
/* 78: 1592, 23 */ "Remote address changed\0"
/* 79: 1615, 39 */ "Can not access a needed shared library\0"
/* 80: 1654, 37 */ "Accessing a corrupted shared library\0"
/* 81: 1691, 32 */ ".lib section in a.out corrupted\0"
/* 82: 1723, 48 */ "Attempting to link in too many shared libraries\0"
/* 83: 1771, 38 */ "Cannot exec a shared library directly\0"
/* 84: 1809, 50 */ "Invalid or incomplete multibyte or wide character\0"
/* 85: 1859, 44 */ "Interrupted system call should be restarted\0"
/* 86: 1903, 19 */ "Streams pipe error\0"
/* 87: 1922, 15 */ "Too many users\0"
/* 88: 1937, 31 */ "Socket operation on non-socket\0"
/* 89: 1968, 29 */ "Destination address required\0"
/* 90: 1997, 17 */ "Message too long\0"
/* 91: 2014, 31 */ "Protocol wrong type for socket\0"
/* 92: 2045, 23 */ "Protocol not available\0"
/* 93: 2068, 23 */ "Protocol not supported\0"
/* 94: 2091, 26 */ "Socket type not supported\0"
/* 95: 2117, 24 */ "Operation not supported\0"
/* 96: 2141, 30 */ "Protocol family not supported\0"
/* 97: 2171, 41 */ "Address family not supported by protocol\0"
/* 98: 2212, 23 */ "Address already in use\0"
/* 99: 2235, 32 */ "Cannot assign requested address\0"
/* 100: 2267, 16 */ "Network is down\0"
/* 101: 2283, 23 */ "Network is unreachable\0"
/* 102: 2306, 36 */ "Network dropped connection on reset\0"
/* 103: 2342, 33 */ "Software caused connection abort\0"
/* 104: 2375, 25 */ "Connection reset by peer\0"
/* 105: 2400, 26 */ "No buffer space available\0"
/* 106: 2426, 40 */ "Transport endpoint is already connected\0"
/* 107: 2466, 36 */ "Transport endpoint is not connected\0"
/* 108: 2502, 46 */ "Cannot send after transport endpoint shutdown\0"
/* 109: 2548, 35 */ "Too many references: cannot splice\0"
/* 110: 2583, 21 */ "Connection timed out\0"
/* 111: 2604, 19 */ "Connection refused\0"
/* 112: 2623, 13 */ "Host is down\0"
/* 113: 2636, 17 */ "No route to host\0"
/* 114: 2653, 30 */ "Operation already in progress\0"
/* 115: 2683, 26 */ "Operation now in progress\0"
/* 116: 2709, 22 */ "Stale NFS file handle\0"
/* 117: 2731, 25 */ "Structure needs cleaning\0"
/* 118: 2756, 28 */ "Not a XENIX named type file\0"
/* 119: 2784, 30 */ "No XENIX semaphores available\0"
/* 120: 2814, 21 */ "Is a named type file\0"
/* 121: 2835, 17 */ "Remote I/O error\0"
/* 122: 2852, 20 */ "Disk quota exceeded\0"
/* 123: 2872, 16 */ "No medium found\0"
/* 124: 2888, 18 */ "Wrong medium type"
#if defined(__mips__) || defined(__sparc__)
"\0"
/* 125: 2906, 28 */ "File locking deadlock error"
#endif
/* Note: for mips we are ignoring ECANCELED since glibc doesn't have a
* corresponsding message.*/
};
 
#endif
/**********************************************************************/
#if defined(L_sys_errlist) && defined(__UCLIBC_HAS_SYS_ERRLIST__)
 
link_warning(_sys_errlist, "sys_nerr and sys_errlist are obsolete and uClibc support for them (in at least some configurations) will probably be unavailable in the near future.")
 
const char *const sys_errlist[] = {
[0] = _string_syserrmsgs + 0,
[EPERM] = _string_syserrmsgs + 8,
[ENOENT] = _string_syserrmsgs + 32,
[ESRCH] = _string_syserrmsgs + 58,
[EINTR] = _string_syserrmsgs + 74,
[EIO] = _string_syserrmsgs + 98,
[ENXIO] = _string_syserrmsgs + 117,
[E2BIG] = _string_syserrmsgs + 143,
[ENOEXEC] = _string_syserrmsgs + 166,
[EBADF] = _string_syserrmsgs + 184,
[ECHILD] = _string_syserrmsgs + 204,
[EAGAIN] = _string_syserrmsgs + 223,
[ENOMEM] = _string_syserrmsgs + 256,
[EACCES] = _string_syserrmsgs + 279,
[EFAULT] = _string_syserrmsgs + 297,
[ENOTBLK] = _string_syserrmsgs + 309,
[EBUSY] = _string_syserrmsgs + 331,
[EEXIST] = _string_syserrmsgs + 355,
[EXDEV] = _string_syserrmsgs + 367,
[ENODEV] = _string_syserrmsgs + 393,
[ENOTDIR] = _string_syserrmsgs + 408,
[EISDIR] = _string_syserrmsgs + 424,
[EINVAL] = _string_syserrmsgs + 439,
[ENFILE] = _string_syserrmsgs + 456,
[EMFILE] = _string_syserrmsgs + 486,
[ENOTTY] = _string_syserrmsgs + 506,
[ETXTBSY] = _string_syserrmsgs + 537,
[EFBIG] = _string_syserrmsgs + 552,
[ENOSPC] = _string_syserrmsgs + 567,
[ESPIPE] = _string_syserrmsgs + 591,
[EROFS] = _string_syserrmsgs + 604,
[EMLINK] = _string_syserrmsgs + 626,
[EPIPE] = _string_syserrmsgs + 641,
[EDOM] = _string_syserrmsgs + 653,
[ERANGE] = _string_syserrmsgs + 686,
[EDEADLK] = _string_syserrmsgs + 716,
[ENAMETOOLONG] = _string_syserrmsgs + 742,
[ENOLCK] = _string_syserrmsgs + 761,
[ENOSYS] = _string_syserrmsgs + 780,
[ENOTEMPTY] = _string_syserrmsgs + 805,
[ELOOP] = _string_syserrmsgs + 825,
/* _string_syserrmsgs + 859, */
[ENOMSG] = _string_syserrmsgs + 860,
[EIDRM] = _string_syserrmsgs + 887,
[ECHRNG] = _string_syserrmsgs + 906,
[EL2NSYNC] = _string_syserrmsgs + 934,
[EL3HLT] = _string_syserrmsgs + 959,
[EL3RST] = _string_syserrmsgs + 974,
[ELNRNG] = _string_syserrmsgs + 988,
[EUNATCH] = _string_syserrmsgs + 1013,
[ENOCSI] = _string_syserrmsgs + 1042,
[EL2HLT] = _string_syserrmsgs + 1069,
[EBADE] = _string_syserrmsgs + 1084,
[EBADR] = _string_syserrmsgs + 1101,
[EXFULL] = _string_syserrmsgs + 1128,
[ENOANO] = _string_syserrmsgs + 1142,
[EBADRQC] = _string_syserrmsgs + 1151,
[EBADSLT] = _string_syserrmsgs + 1172,
/* _string_syserrmsgs + 1185, */
[EBFONT] = _string_syserrmsgs + 1186,
[ENOSTR] = _string_syserrmsgs + 1207,
[ENODATA] = _string_syserrmsgs + 1227,
[ETIME] = _string_syserrmsgs + 1245,
[ENOSR] = _string_syserrmsgs + 1259,
[ENONET] = _string_syserrmsgs + 1284,
[ENOPKG] = _string_syserrmsgs + 1314,
[EREMOTE] = _string_syserrmsgs + 1336,
[ENOLINK] = _string_syserrmsgs + 1353,
[EADV] = _string_syserrmsgs + 1375,
[ESRMNT] = _string_syserrmsgs + 1391,
[ECOMM] = _string_syserrmsgs + 1405,
[EPROTO] = _string_syserrmsgs + 1433,
[EMULTIHOP] = _string_syserrmsgs + 1448,
[EDOTDOT] = _string_syserrmsgs + 1467,
[EBADMSG] = _string_syserrmsgs + 1486,
[EOVERFLOW] = _string_syserrmsgs + 1498,
[ENOTUNIQ] = _string_syserrmsgs + 1536,
[EBADFD] = _string_syserrmsgs + 1563,
[EREMCHG] = _string_syserrmsgs + 1592,
[ELIBACC] = _string_syserrmsgs + 1615,
[ELIBBAD] = _string_syserrmsgs + 1654,
[ELIBSCN] = _string_syserrmsgs + 1691,
[ELIBMAX] = _string_syserrmsgs + 1723,
[ELIBEXEC] = _string_syserrmsgs + 1771,
[EILSEQ] = _string_syserrmsgs + 1809,
[ERESTART] = _string_syserrmsgs + 1859,
[ESTRPIPE] = _string_syserrmsgs + 1903,
[EUSERS] = _string_syserrmsgs + 1922,
[ENOTSOCK] = _string_syserrmsgs + 1937,
[EDESTADDRREQ] = _string_syserrmsgs + 1968,
[EMSGSIZE] = _string_syserrmsgs + 1997,
[EPROTOTYPE] = _string_syserrmsgs + 2014,
[ENOPROTOOPT] = _string_syserrmsgs + 2045,
[EPROTONOSUPPORT] = _string_syserrmsgs + 2068,
[ESOCKTNOSUPPORT] = _string_syserrmsgs + 2091,
[EOPNOTSUPP] = _string_syserrmsgs + 2117,
[EPFNOSUPPORT] = _string_syserrmsgs + 2141,
[EAFNOSUPPORT] = _string_syserrmsgs + 2171,
[EADDRINUSE] = _string_syserrmsgs + 2212,
[EADDRNOTAVAIL] = _string_syserrmsgs + 2235,
[ENETDOWN] = _string_syserrmsgs + 2267,
[ENETUNREACH] = _string_syserrmsgs + 2283,
[ENETRESET] = _string_syserrmsgs + 2306,
[ECONNABORTED] = _string_syserrmsgs + 2342,
[ECONNRESET] = _string_syserrmsgs + 2375,
[ENOBUFS] = _string_syserrmsgs + 2400,
[EISCONN] = _string_syserrmsgs + 2426,
[ENOTCONN] = _string_syserrmsgs + 2466,
[ESHUTDOWN] = _string_syserrmsgs + 2502,
[ETOOMANYREFS] = _string_syserrmsgs + 2548,
[ETIMEDOUT] = _string_syserrmsgs + 2583,
[ECONNREFUSED] = _string_syserrmsgs + 2604,
[EHOSTDOWN] = _string_syserrmsgs + 2623,
[EHOSTUNREACH] = _string_syserrmsgs + 2636,
[EALREADY] = _string_syserrmsgs + 2653,
[EINPROGRESS] = _string_syserrmsgs + 2683,
[ESTALE] = _string_syserrmsgs + 2709,
[EUCLEAN] = _string_syserrmsgs + 2731,
[ENOTNAM] = _string_syserrmsgs + 2756,
[ENAVAIL] = _string_syserrmsgs + 2784,
[EISNAM] = _string_syserrmsgs + 2814,
[EREMOTEIO] = _string_syserrmsgs + 2835,
[EDQUOT] = _string_syserrmsgs + 2852,
[ENOMEDIUM] = _string_syserrmsgs + 2872,
[EMEDIUMTYPE] = _string_syserrmsgs + 2888,
 
#if EDEADLOCK != EDEADLK
[EDEADLOCK] = _string_syserrmsgs + 2906,
#endif
 
#if EWOULDBLOCK != EAGAIN
#error EWOULDBLOCK does not equal EAGAIN
#endif
 
/* For now, ignore the other arch-specific errors. glibc only maps EPROCLIM. */
 
/* some other mips errors */
#ifdef ECANCELED
#endif
#ifdef EINIT
#endif
#ifdef EREMDEV
#endif
 
/* some other sparc errors */
#ifdef EPROCLIM
#endif
#ifdef ERREMOTE
#endif
};
 
int sys_nerr = sizeof(sys_errlist)/sizeof(sys_errlist[0]);
 
#endif
/**********************************************************************/
#ifdef L_wmemcpy
#define L_memcpy
#define Wmemcpy wmemcpy
#else
#define Wmemcpy memcpy
#endif
 
#ifdef L_memcpy
 
Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
{
register Wchar *r1 = s1;
register const Wchar *r2 = s2;
 
#ifdef __BCC__
while (n--) {
*r1++ = *r2++;
}
#else
while (n) {
*r1++ = *r2++;
--n;
}
#endif
 
return s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wmemmove
#define L_memmove
#define Wmemmove wmemmove
#else
#define Wmemmove memmove
#endif
 
#ifdef L_memmove
 
Wvoid *Wmemmove(Wvoid *s1, const Wvoid *s2, size_t n)
{
#ifdef __BCC__
register Wchar *s = (Wchar *) s1;
register const Wchar *p = (const Wchar *) s2;
 
if (p >= s) {
while (n--) {
*s++ = *p++;
}
} else {
s += n;
p += n;
while (n--) {
*--s = *--p;
}
}
 
return s1;
#else
register Wchar *s = (Wchar *) s1;
register const Wchar *p = (const Wchar *) s2;
 
if (p >= s) {
while (n) {
*s++ = *p++;
--n;
}
} else {
while (n) {
--n;
s[n] = p[n];
}
}
 
return s1;
#endif
}
 
#endif
/**********************************************************************/
#ifdef L_wcscpy
#define L_strcpy
#define Wstrcpy wcscpy
#else
#define Wstrcpy strcpy
#endif
 
#ifdef L_strcpy
 
Wchar *Wstrcpy(Wchar * __restrict s1, const Wchar * __restrict s2)
{
register Wchar *s = s1;
 
#ifdef __BCC__
do {
*s = *s2++;
} while (*s++ != 0);
#else
while ( (*s++ = *s2++) != 0 );
#endif
 
return s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wcsncpy
#define L_strncpy
#define Wstrncpy wcsncpy
#else
#define Wstrncpy strncpy
#endif
 
#ifdef L_strncpy
 
Wchar *Wstrncpy(Wchar * __restrict s1, register const Wchar * __restrict s2,
size_t n)
{
register Wchar *s = s1;
 
#ifdef __BCC__
while (n--) {
if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
++s;
}
#else
while (n) {
if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
++s;
--n;
}
#endif
return s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wcscat
#define L_strcat
#define Wstrcat wcscat
#else
#define Wstrcat strcat
#endif
 
#ifdef L_strcat
 
Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2)
{
register Wchar *s = s1;
 
while (*s++);
--s;
while ((*s++ = *s2++) != 0);
 
return s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wcsncat
#define L_strncat
#define Wstrncat wcsncat
#else
#define Wstrncat strncat
#endif
 
#ifdef L_strncat
 
Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2,
size_t n)
{
register Wchar *s = s1;
 
while (*s++);
--s;
#if __BCC__
while (n-- && ((*s = *s2++) != 0)) ++s;
#else
while (n && ((*s = *s2++) != 0)) {
--n;
++s;
}
#endif
*s = 0;
 
return s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wmemcmp
#define L_memcmp
#define Wmemcmp wmemcmp
#else
#define Wmemcmp memcmp
#endif
 
#ifdef L_memcmp
 
#ifndef L_wmemcmp
weak_alias(memcmp,bcmp);
#endif
 
int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
{
register const Wuchar *r1 = (const Wuchar *) s1;
register const Wuchar *r2 = (const Wuchar *) s2;
 
#ifdef WANT_WIDE
while (n && (*r1 == *r2)) {
++r1;
++r2;
--n;
}
 
return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1);
#else
int r = 0;
 
while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0));
 
return r;
#endif
}
 
#endif
/**********************************************************************/
#ifdef L_wcscmp
#define L_strcmp
#define Wstrcmp wcscmp
#else
#define Wstrcmp strcmp
#endif
 
#ifdef L_strcmp
 
#ifdef __LOCALE_C_ONLY
#ifdef L_wcscmp
weak_alias(wcscmp,wcscoll);
#else /* L_wcscmp */
weak_alias(strcmp,strcoll);
#endif /* L_wcscmp */
#endif /* __LOCALE_C_ONLY */
 
int Wstrcmp(register const Wchar *s1, register const Wchar *s2)
{
#ifdef WANT_WIDE
while (*((Wuchar *)s1) == *((Wuchar *)s2)) {
if (!*s1++) {
return 0;
}
++s2;
}
 
return (*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1;
#else
int r;
 
while (((r = ((int)(*((Wuchar *)s1))) - *((Wuchar *)s2++))
== 0) && *s1++);
return r;
#endif
}
#endif
/**********************************************************************/
#ifdef L_wcsncmp
#define L_strncmp
#define Wstrncmp wcsncmp
#else
#define Wstrncmp strncmp
#endif
 
#ifdef L_strncmp
 
int Wstrncmp(register const Wchar *s1, register const Wchar *s2, size_t n)
{
#ifdef WANT_WIDE
while (n && (*((Wuchar *)s1) == *((Wuchar *)s2))) {
if (!*s1++) {
return 0;
}
++s2;
--n;
}
 
return (n == 0) ? 0 : ((*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1);
#else
int r = 0;
 
while (n--
&& ((r = ((int)(*((unsigned char *)s1))) - *((unsigned char *)s2++))
== 0)
&& *s1++);
 
return r;
#endif
}
 
#endif
/**********************************************************************/
#ifdef L_wmemchr
#define L_memchr
#define Wmemchr wmemchr
#else
#define Wmemchr memchr
#endif
 
#ifdef L_memchr
 
Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n)
{
register const Wuchar *r = (const Wuchar *) s;
#ifdef __BCC__
/* bcc can optimize the counter if it thinks it is a pointer... */
register const char *np = (const char *) n;
#else
#define np n
#endif
 
while (np) {
if (*r == ((Wuchar)c)) {
return (Wvoid *) r; /* silence the warning */
}
++r;
--np;
}
 
return NULL;
}
#undef np
 
#endif
/**********************************************************************/
#ifdef L_wcschr
#define L_strchr
#define Wstrchr wcschr
#else
#define Wstrchr strchr
#endif
 
#ifdef L_strchr
 
#ifndef L_wcschr
weak_alias(strchr,index);
#endif
 
Wchar *Wstrchr(register const Wchar *s, Wint c)
{
do {
if (*s == ((Wchar)c)) {
return (Wchar *) s; /* silence the warning */
}
} while (*s++);
 
return NULL;
}
 
#endif
/**********************************************************************/
#ifdef L_wcscspn
#define L_strcspn
#define Wstrcspn wcscspn
#else
#define Wstrcspn strcspn
#endif
 
#ifdef L_strcspn
 
size_t Wstrcspn(const Wchar *s1, const Wchar *s2)
{
register const Wchar *s;
register const Wchar *p;
 
for ( s=s1 ; *s ; s++ ) {
for ( p=s2 ; *p ; p++ ) {
if (*p == *s) goto done;
}
}
done:
return s - s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wcspbrk
#define L_strpbrk
#define Wstrpbrk wcspbrk
#else
#define Wstrpbrk strpbrk
#endif
 
#ifdef L_strpbrk
 
Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2)
{
register const Wchar *s;
register const Wchar *p;
 
for ( s=s1 ; *s ; s++ ) {
for ( p=s2 ; *p ; p++ ) {
if (*p == *s) return (Wchar *) s; /* silence the warning */
}
}
return NULL;
}
#endif
/**********************************************************************/
#ifdef L_wcsrchr
#define L_strrchr
#define Wstrrchr wcsrchr
#else
#define Wstrrchr strrchr
#endif
 
#ifdef L_strrchr
 
#ifndef L_wcsrchr
weak_alias(strrchr,rindex);
#endif
 
Wchar *Wstrrchr(register const Wchar *s, Wint c)
{
register const Wchar *p;
 
p = NULL;
do {
if (*s == (Wchar) c) {
p = s;
}
} while (*s++);
 
return (Wchar *) p; /* silence the warning */
}
 
#endif
/**********************************************************************/
#ifdef L_wcsspn
#define L_strspn
#define Wstrspn wcsspn
#else
#define Wstrspn strspn
#endif
 
#ifdef L_strspn
 
size_t Wstrspn(const Wchar *s1, const Wchar *s2)
{
register const Wchar *s = s1;
register const Wchar *p = s2;
 
while (*p) {
if (*p++ == *s) {
++s;
p = s2;
}
}
return s - s1;
}
 
#endif
/**********************************************************************/
#ifdef L_wcsstr
#define L_strstr
#define Wstrstr wcsstr
#else
#define Wstrstr strstr
#endif
 
#ifdef L_strstr
 
/* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */
 
#ifdef L_wcsstr
weak_alias(wcsstr,wcswcs);
#endif
 
Wchar *Wstrstr(const Wchar *s1, const Wchar *s2)
{
register const Wchar *s = s1;
register const Wchar *p = s2;
 
do {
if (!*p) {
return (Wchar *) s1;;
}
if (*p == *s) {
++p;
++s;
} else {
p = s2;
if (!*s) {
return NULL;
}
s = ++s1;
}
} while (1);
}
 
#endif
/**********************************************************************/
#undef Wstrspn
#undef Wstrpbrk
 
#ifdef L_wcstok
#define L_strtok_r
#define Wstrtok_r wcstok
#define Wstrspn wcsspn
#define Wstrpbrk wcspbrk
#else
#define Wstrtok_r strtok_r
#define Wstrspn strspn
#define Wstrpbrk strpbrk
#endif
 
#ifdef L_strtok_r
 
Wchar *Wstrtok_r(Wchar * __restrict s1, const Wchar * __restrict s2,
Wchar ** __restrict next_start)
{
register Wchar *s;
register Wchar *p;
 
#if 1
if (((s = s1) != NULL) || ((s = *next_start) != NULL)) {
if (*(s += Wstrspn(s, s2))) {
if ((p = Wstrpbrk(s, s2)) != NULL) {
*p++ = 0;
}
} else {
p = s = NULL;
}
*next_start = p;
}
return s;
#else
if (!(s = s1)) {
s = *next_start;
}
if (s && *(s += Wstrspn(s, s2))) {
if (*(p = s + Wstrcspn(s, s2))) {
*p++ = 0;
}
*next_start = p;
return s;
}
return NULL; /* TODO: set *next_start = NULL for safety? */
#endif
}
 
#endif
/**********************************************************************/
/* #ifdef L_wcstok */
/* #define L_strtok */
/* #define Wstrtok wcstok */
/* #define Wstrtok_r wcstok_r */
/* #else */
/* #define Wstrtok strtok */
/* #define Wstrtok_r strtok_r */
/* #endif */
 
#ifdef L_strtok
#define Wstrtok strtok
#define Wstrtok_r strtok_r
 
Wchar *Wstrtok(Wchar * __restrict s1, const Wchar * __restrict s2)
{
static Wchar *next_start; /* Initialized to 0 since in bss. */
return Wstrtok_r(s1, s2, &next_start);
}
 
#endif
/**********************************************************************/
#ifdef L_wmemset
#define L_memset
#define Wmemset wmemset
#else
#define Wmemset memset
#endif
 
#ifdef L_memset
 
Wvoid *Wmemset(Wvoid *s, Wint c, size_t n)
{
register Wuchar *p = (Wuchar *) s;
#ifdef __BCC__
/* bcc can optimize the counter if it thinks it is a pointer... */
register const char *np = (const char *) n;
#else
#define np n
#endif
 
while (np) {
*p++ = (Wuchar) c;
--np;
}
 
return s;
}
#undef np
 
#endif
/**********************************************************************/
#ifdef L_wcslen
#define L_strlen
#define Wstrlen wcslen
#else
#define Wstrlen strlen
#endif
 
#ifdef L_strlen
 
size_t Wstrlen(const Wchar *s)
{
register const Wchar *p;
 
for (p=s ; *p ; p++);
 
return p - s;
}
 
#endif
/**********************************************************************/
/* ANSI/ISO end here */
/**********************************************************************/
#ifdef L_ffs
 
int ffs(int i)
{
#if 1
/* inlined binary search method */
char n = 1;
#if UINT_MAX == 0xffffU
/* nothing to do here -- just trying to avoiding possible problems */
#elif UINT_MAX == 0xffffffffU
if (!(i & 0xffff)) {
n += 16;
i >>= 16;
}
#else
#error ffs needs rewriting!
#endif
 
if (!(i & 0xff)) {
n += 8;
i >>= 8;
}
if (!(i & 0x0f)) {
n += 4;
i >>= 4;
}
if (!(i & 0x03)) {
n += 2;
i >>= 2;
}
return (i) ? (n + ((i+1) & 0x01)) : 0;
 
#else
/* linear search -- slow, but small */
int n;
 
for (n = 0 ; i ; ++n) {
i >>= 1;
}
return n;
#endif
}
 
#endif
/**********************************************************************/
#if defined(L_strcasecmp) || defined(L_strcasecmp_l) || defined(L_wcscasecmp) || defined(L_wcscasecmp_l)
 
#if defined(L_wcscasecmp) || defined(L_wcscasecmp_l)
 
#define strcasecmp wcscasecmp
#define strcasecmp_l wcscasecmp_l
#define __strcasecmp_l __wcscasecmp_l
#ifdef __UCLIBC_DO_XLOCALE
#define TOLOWER(C) __towlower_l((C), locale_arg)
#else
#define TOLOWER(C) towlower((C))
#endif
 
#else /* defined(L_wcscasecmp) || defined(L_wcscasecmp_l) */
 
#ifdef __UCLIBC_DO_XLOCALE
#define TOLOWER(C) __tolower_l((C), locale_arg)
#else
#define TOLOWER(C) tolower((C))
#endif
 
#endif /* defined(L_wcscasecmp) || defined(L_wcscasecmp_l) */
 
 
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
 
int strcasecmp(register const Wchar *s1, register const Wchar *s2)
{
return __strcasecmp_l(s1, s2, __UCLIBC_CURLOCALE);
}
 
#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
 
int __XL(strcasecmp)(register const Wchar *s1, register const Wchar *s2
__LOCALE_PARAM )
{
#ifdef WANT_WIDE
while ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2))) {
if (!*s1++) {
return 0;
}
++s2;
}
 
return (((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1;
/* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
#else
int r = 0;
 
while ( ((s1 == s2) ||
!(r = ((int)( TOLOWER(*((Wuchar *)s1))))
- TOLOWER(*((Wuchar *)s2))))
&& (++s2, *s1++));
 
return r;
#endif
}
 
__XL_ALIAS(strcasecmp)
 
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
 
#endif
/**********************************************************************/
#if defined(L_strncasecmp) || defined(L_strncasecmp_l) || defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l)
 
#if defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l)
 
#define strncasecmp wcsncasecmp
#define strncasecmp_l wcsncasecmp_l
#define __strncasecmp_l __wcsncasecmp_l
#ifdef __UCLIBC_DO_XLOCALE
#define TOLOWER(C) __towlower_l((C), locale_arg)
#else
#define TOLOWER(C) towlower((C))
#endif
 
#else /* defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l) */
 
#ifdef __UCLIBC_DO_XLOCALE
#define TOLOWER(C) __tolower_l((C), locale_arg)
#else
#define TOLOWER(C) tolower((C))
#endif
 
#endif /* defined(L_wcsncasecmp) || defined(L_wcsncasecmp_l) */
 
 
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
 
int strncasecmp(register const Wchar *s1, register const Wchar *s2, size_t n)
{
return __strncasecmp_l(s1, s2, n, __UCLIBC_CURLOCALE);
}
 
#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
 
int __XL(strncasecmp)(register const Wchar *s1, register const Wchar *s2,
size_t n __LOCALE_PARAM )
{
#ifdef WANT_WIDE
while (n && ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2)))) {
if (!*s1++) {
return 0;
}
++s2;
--n;
}
 
return (n == 0)
? 0
: ((((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1);
/* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
#else
int r = 0;
 
while ( n
&& ((s1 == s2) ||
!(r = ((int)( TOLOWER(*((unsigned char *)s1))))
- TOLOWER(*((unsigned char *)s2))))
&& (--n, ++s2, *s1++));
return r;
#endif
}
 
__XL_ALIAS(strncasecmp)
 
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
 
#endif
/**********************************************************************/
#ifdef L_wcsnlen
#define L_strnlen
#define Wstrnlen wcsnlen
#else
#define Wstrnlen strnlen
#endif
 
#ifdef L_strnlen
 
size_t Wstrnlen(const Wchar *s, size_t max)
{
register const Wchar *p = s;
#ifdef __BCC__
/* bcc can optimize the counter if it thinks it is a pointer... */
register const char *maxp = (const char *) max;
#else
#define maxp max
#endif
 
while (maxp && *p) {
++p;
--maxp;
}
 
return p - s;
}
#undef maxp
#endif
/**********************************************************************/
/* No wide analog. */
 
#ifdef L_memccpy
 
void *memccpy(void * __restrict s1, const void * __restrict s2, int c, size_t n)
{
register char *r1 = s1;
register const char *r2 = s2;
 
while (n-- && (((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c)));
 
return (n == (size_t) -1) ? NULL : r1;
}
 
#endif
/**********************************************************************/
#undef Wstrlen
#undef Wstrcpy
 
#ifdef L_wcsdup
#define L_strdup
#define Wstrdup wcsdup
#define Wstrlen wcslen
#define Wstrcpy wcscpy
#else
#define Wstrdup strdup
#define Wstrlen strlen
#define Wstrcpy strcpy
#endif
 
#ifdef L_strdup
 
Wchar *Wstrdup(register const Wchar *s1)
{
register Wchar *s;
 
if ((s = malloc((Wstrlen(s1) + 1) * sizeof(Wchar))) != NULL) {
Wstrcpy(s, s1);
}
 
return s;
}
 
#endif
/**********************************************************************/
#ifdef L_strerror
 
char *strerror(int errnum)
{
static char buf[_STRERROR_BUFSIZE];
 
_susv3_strerror_r(errnum, buf, sizeof(buf));
 
return buf;
}
 
#endif
/**********************************************************************/
/* SUSv3 functions. */
/**********************************************************************/
#ifdef L__susv3_strerror_r
 
#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
 
static const unsigned char estridx[] = {
0, /* success is always 0 */
EPERM,
ENOENT,
ESRCH,
EINTR,
EIO,
ENXIO,
E2BIG,
ENOEXEC,
EBADF,
ECHILD,
EAGAIN,
ENOMEM,
EACCES,
EFAULT,
ENOTBLK,
EBUSY,
EEXIST,
EXDEV,
ENODEV,
ENOTDIR,
EISDIR,
EINVAL,
ENFILE,
EMFILE,
ENOTTY,
ETXTBSY,
EFBIG,
ENOSPC,
ESPIPE,
EROFS,
EMLINK,
EPIPE,
EDOM,
ERANGE,
EDEADLK,
ENAMETOOLONG,
ENOLCK,
ENOSYS,
ENOTEMPTY,
ELOOP,
0,
ENOMSG,
EIDRM,
ECHRNG,
EL2NSYNC,
EL3HLT,
EL3RST,
ELNRNG,
EUNATCH,
ENOCSI,
EL2HLT,
EBADE,
EBADR,
EXFULL,
ENOANO,
EBADRQC,
EBADSLT,
0,
EBFONT,
ENOSTR,
ENODATA,
ETIME,
ENOSR,
ENONET,
ENOPKG,
EREMOTE,
ENOLINK,
EADV,
ESRMNT,
ECOMM,
EPROTO,
EMULTIHOP,
EDOTDOT,
EBADMSG,
EOVERFLOW,
ENOTUNIQ,
EBADFD,
EREMCHG,
ELIBACC,
ELIBBAD,
ELIBSCN,
ELIBMAX,
ELIBEXEC,
EILSEQ,
ERESTART,
ESTRPIPE,
EUSERS,
ENOTSOCK,
EDESTADDRREQ,
EMSGSIZE,
EPROTOTYPE,
ENOPROTOOPT,
EPROTONOSUPPORT,
ESOCKTNOSUPPORT,
EOPNOTSUPP,
EPFNOSUPPORT,
EAFNOSUPPORT,
EADDRINUSE,
EADDRNOTAVAIL,
ENETDOWN,
ENETUNREACH,
ENETRESET,
ECONNABORTED,
ECONNRESET,
ENOBUFS,
EISCONN,
ENOTCONN,
ESHUTDOWN,
ETOOMANYREFS,
ETIMEDOUT,
ECONNREFUSED,
EHOSTDOWN,
EHOSTUNREACH,
EALREADY,
EINPROGRESS,
ESTALE,
EUCLEAN,
ENOTNAM,
ENAVAIL,
EISNAM,
EREMOTEIO,
#ifdef __mips__
0, /* mips has an outrageous value for this... */
#else
EDQUOT,
#endif
ENOMEDIUM,
EMEDIUMTYPE,
#if defined(__mips__) || defined(__sparc__)
EDEADLOCK,
#endif
};
 
#endif
 
int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
register char *s;
int i, retval;
char buf[_STRERROR_BUFSIZE];
static const char unknown[] = {
'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
};
 
retval = EINVAL;
 
 
#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
 
#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
/* Need to translate errno to string index. */
for (i = 0 ; i < sizeof(estridx)/sizeof(estridx[0]) ; i++) {
if (estridx[i] == errnum) {
goto GOT_ESTRIDX;
}
}
i = INT_MAX; /* Failed, but may need to check mips special case. */
#ifdef __mips__
if (errnum == EDQUOT) { /* Deal with large EDQUOT value on mips */
i = 122;
}
#endif /* __mips__ */
GOT_ESTRIDX:
#else
/* No errno to string index translation needed. */
i = errnum;
#endif
 
if (((unsigned int) i) < _SYS_NERR) {
/* Trade time for space. This function should rarely be called
* so rather than keeping an array of pointers for the different
* messages, just run through the buffer until we find the
* correct string. */
for (s = (char *) _string_syserrmsgs ; i ; ++s) {
if (!*s) {
--i;
}
}
if (*s) { /* Make sure we have an actual message. */
retval = 0;
goto GOT_MESG;
}
}
 
#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
 
s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
memcpy(s, unknown, sizeof(unknown));
 
GOT_MESG:
if (!strerrbuf) { /* SUSv3 */
buflen = 0;
}
i = strlen(s) + 1;
if (i > buflen) {
i = buflen;
retval = ERANGE;
}
 
if (i) {
memcpy(strerrbuf, s, i);
strerrbuf[i-1] = 0; /* In case buf was too small. */
}
 
if (retval) {
__set_errno(retval);
}
 
return retval;
}
 
#else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
 
int _susv3_strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
register char *s;
int i, retval;
char buf[_STRERROR_BUFSIZE];
static const char unknown[] = {
'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
};
 
s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
memcpy(s, unknown, sizeof(unknown));
 
if (!strerrbuf) { /* SUSv3 */
buflen = 0;
}
 
retval = EINVAL;
 
i = buf + sizeof(buf) - s;
 
if (i > buflen) {
i = buflen;
retval = ERANGE;
}
 
if (i) {
memcpy(strerrbuf, s, i);
strerrbuf[i-1] = 0; /* In case buf was too small. */
}
 
__set_errno(retval);
 
return retval;
}
 
#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
 
#endif
/**********************************************************************/
/* GNU extension functions. */
/**********************************************************************/
#ifdef L__glibc_strerror_r
 
weak_alias(_glibc_strerror_r,__strerror_r);
 
char *_glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
_susv3_strerror_r(errnum, strerrbuf, buflen);
 
return strerrbuf;
}
 
#endif
/**********************************************************************/
#ifdef L_memmem
 
void *memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen)
{
register const char *ph;
register const char *pn;
const char *plast;
size_t n;
 
if (needlelen == 0) {
return (void *) haystack;
}
 
if (haystacklen >= needlelen) {
ph = (const char *) haystack;
pn = (const char *) needle;
plast = ph + (haystacklen - needlelen);
 
do {
n = 0;
while (ph[n] == pn[n]) {
if (++n == needlelen) {
return (void *) ph;
}
}
} while (++ph <= plast);
}
 
return NULL;
}
 
#endif
/**********************************************************************/
#ifdef L_wmempcpy
#define L_mempcpy
#define Wmempcpy wmempcpy
#else
#define Wmempcpy mempcpy
#endif
 
#ifdef L_mempcpy
 
#ifndef L_wmempcpy
/* uClibc's old string implementation did this to cater to some app. */
weak_alias(mempcpy,__mempcpy);
#endif
 
Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
{
register Wchar *r1 = s1;
register const Wchar *r2 = s2;
 
#ifdef __BCC__
while (n--) {
*r1++ = *r2++;
}
#else
while (n) {
*r1++ = *r2++;
--n;
}
#endif
 
return r1;
}
 
#endif
/**********************************************************************/
#ifdef L_memrchr
 
void *memrchr(const void *s, int c, size_t n)
{
register const unsigned char *r;
#ifdef __BCC__
/* bcc can optimize the counter if it thinks it is a pointer... */
register const char *np = (const char *) n;
#else
#define np n
#endif
r = ((unsigned char *)s) + ((size_t) np);
 
while (np) {
if (*--r == ((unsigned char)c)) {
return (void *) r; /* silence the warning */
}
--np;
}
 
return NULL;
}
#undef np
 
#endif
/**********************************************************************/
#ifdef L_wcpcpy
#define L_stpcpy
#define Wstpcpy wcpcpy
#else
#define Wstpcpy stpcpy
#endif
 
#ifdef L_stpcpy
 
Wchar *Wstpcpy(register Wchar * __restrict s1, const Wchar * __restrict s2)
{
#ifdef __BCC__
do {
*s1 = *s2++;
} while (*s1++ != 0);
#else
while ( (*s1++ = *s2++) != 0 );
#endif
 
return s1 - 1;
}
 
#endif
/**********************************************************************/
#ifdef L_wcpncpy
#define L_stpncpy
#define Wstpncpy wcpncpy
#else
#define Wstpncpy stpncpy
#endif
 
#ifdef L_stpncpy
 
Wchar *Wstpncpy(register Wchar * __restrict s1,
register const Wchar * __restrict s2,
size_t n)
{
Wchar *s = s1;
const Wchar *p = s2;
 
#ifdef __BCC__
while (n--) {
if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
++s;
}
return s1 + (s2 - p);
#else
while (n) {
if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
++s;
--n;
}
return s1 + (s2 - p);
#endif
}
 
#endif
/**********************************************************************/
#ifdef L_bzero
 
void bzero(void *s, size_t n)
{
register unsigned char *p = s;
#ifdef __BCC__
/* bcc can optimize the counter if it thinks it is a pointer... */
register const char *np = (const char *) n;
#else
#define np n
#endif
 
while (np) {
*p++ = 0;
--np;
}
}
#undef np
 
#endif
/**********************************************************************/
#ifdef L_bcopy
 
void bcopy(const void *s2, void *s1, size_t n)
{
#if 1
memmove(s1, s2, n);
#else
#ifdef __BCC__
register char *s;
register const char *p;
 
s = s1;
p = s2;
if (p >= s) {
while (n--) {
*s++ = *p++;
}
} else {
s += n;
p += n;
while (n--) {
*--s = *--p;
}
}
#else
register char *s;
register const char *p;
 
s = s1;
p = s2;
if (p >= s) {
while (n) {
*s++ = *p++;
--n;
}
} else {
while (n) {
--n;
s[n] = p[n];
}
}
#endif
#endif
}
 
#endif
/**********************************************************************/
#ifdef L_strcasestr
 
char *strcasestr(const char *s1, const char *s2)
{
register const char *s = s1;
register const char *p = s2;
 
#if 1
do {
if (!*p) {
return (char *) s1;;
}
if ((*p == *s)
|| (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
) {
++p;
++s;
} else {
p = s2;
if (!*s) {
return NULL;
}
s = ++s1;
}
} while (1);
#else
while (*p && *s) {
if ((*p == *s)
|| (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
) {
++p;
++s;
} else {
p = s2;
s = ++s1;
}
}
 
return (*p) ? NULL : (char *) s1;
#endif
}
 
#endif
/**********************************************************************/
#ifdef L_strndup
 
char *strndup(register const char *s1, size_t n)
{
register char *s;
 
n = strnlen(s1,n); /* Avoid problems if s1 not nul-terminated. */
 
if ((s = malloc(n + 1)) != NULL) {
memcpy(s, s1, n);
s[n] = 0;
}
 
return s;
}
 
#endif
/**********************************************************************/
#ifdef L_strsep
 
char *strsep(char ** __restrict s1, const char * __restrict s2)
{
register char *s = *s1;
register char *p;
 
#if 1
p = NULL;
if (s && *s && (p = strpbrk(s, s2))) {
*p++ = 0;
}
#else
if (s && *s && *(p = s + strcspn(s, s2))) {
*p++ = 0;
} else {
p = NULL;
}
#endif
*s1 = p;
return s;
}
 
#endif
/**********************************************************************/
#ifdef L_wcschrnul
#define L_strchrnul
#define __Wstrchrnul __wcschrnul
#define Wstrchrnul wcschrnul
#else
#define __Wstrchrnul __strchrnul
#define Wstrchrnul strchrnul
#endif
 
#ifdef L_strchrnul
 
extern Wchar *__Wstrchrnul(register const Wchar *s, Wint c);
weak_alias(__Wstrchrnul, Wstrchrnul);
 
Wchar *__Wstrchrnul(register const Wchar *s, Wint c)
{
--s;
while (*++s && (*s != ((Wchar)c)));
return (Wchar *) s;
}
 
#endif
/**********************************************************************/
#ifdef L_rawmemchr
 
void *rawmemchr(const void *s, int c)
{
register const unsigned char *r = s;
 
while (*r != ((unsigned char)c)) ++r;
 
return (void *) r; /* silence the warning */
}
 
#endif
/**********************************************************************/
#ifdef L_basename
 
char *basename(const char *path)
{
register const char *s;
register const char *p;
 
p = s = path;
 
while (*s) {
if (*s++ == '/') {
p = s;
}
}
 
return (char *) p;
}
 
#endif
/**********************************************************************/
#ifdef L___xpg_basename
 
char *__xpg_basename(register char *path)
{
static const char null_or_empty[] = ".";
char *first;
register char *last;
 
first = (char *) null_or_empty;
 
if (path && *path) {
first = path;
last = path - 1;
 
do {
if ((*path != '/') && (path > ++last)) {
last = first = path;
}
} while (*++path);
 
if (*first == '/') {
last = first;
}
last[1] = 0;
}
 
return first;
}
 
#endif
/**********************************************************************/
#ifdef L_dirname
 
char *dirname(char *path)
{
static const char null_or_empty_or_noslash[] = ".";
register char *s;
register char *last;
char *first;
 
last = s = path;
 
if (s != NULL) {
 
LOOP:
while (*s && (*s != '/')) ++s;
first = s;
while (*s == '/') ++s;
if (*s) {
last = first;
goto LOOP;
}
 
if (last == path) {
if (*last != '/') {
goto DOT;
}
if ((*++last == '/') && (last[1] == 0)) {
++last;
}
}
*last = 0;
return path;
}
DOT:
return (char *) null_or_empty_or_noslash;
}
 
#endif
/**********************************************************************/
#ifdef L_strlcat
 
/* OpenBSD function:
* Append at most n-1-strlen(dst) chars from src to dst and nul-terminate dst.
* Returns strlen(src) + strlen({original} dst), so truncation occurred if the
* return val is >= n.
* Note: If dst doesn't contain a nul in the first n chars, strlen(dst) is
* taken as n. */
 
size_t strlcat(register char *__restrict dst,
register const char *__restrict src,
size_t n)
{
size_t len;
char dummy[1];
 
len = 0;
 
while (1) {
if (len >= n) {
dst = dummy;
break;
}
if (!*dst) {
break;
}
++dst;
++len;
}
 
while ((*dst = *src) != 0) {
if (++len < n) {
++dst;
}
++src;
}
 
return len;
}
 
#endif
/**********************************************************************/
#ifdef WANT_WIDE
extern size_t __wcslcpy(wchar_t *__restrict dst,
const wchar_t *__restrict src,
size_t n);
#endif
 
 
#ifdef L___wcslcpy
#define L_strlcpy
#define Wstrlcpy __wcslcpy
#ifdef __LOCALE_C_ONLY
weak_alias(__wcslcpy,wcsxfrm);
#endif
#endif
 
#ifdef L_strlcpy
 
#ifndef L___wcslcpy
#define Wstrlcpy strlcpy
#ifdef __LOCALE_C_ONLY
weak_alias(strlcpy,strxfrm);
#endif
#endif
 
/* OpenBSD function:
* Copy at most n-1 chars from src to dst and nul-terminate dst.
* Returns strlen(src), so truncation occurred if the return value is >= n. */
 
size_t Wstrlcpy(register Wchar *__restrict dst,
register const Wchar *__restrict src,
size_t n)
{
const Wchar *src0 = src;
Wchar dummy[1];
 
if (!n) {
dst = dummy;
} else {
--n;
}
 
while ((*dst = *src) != 0) {
if (n) {
--n;
++dst;
}
++src;
}
 
return src - src0;
}
 
#endif
/**********************************************************************/
#if defined(L__string_syssigmsgs) && defined(__UCLIBC_HAS_SIGNUM_MESSAGES__)
 
const char _string_syssigmsgs[] = {
/* 0: 0, 1 */ "\0"
/* 1: 1, 7 */ "Hangup\0"
/* 2: 8, 10 */ "Interrupt\0"
/* 3: 18, 5 */ "Quit\0"
/* 4: 23, 20 */ "Illegal instruction\0"
/* 5: 43, 22 */ "Trace/breakpoint trap\0"
/* 6: 65, 8 */ "Aborted\0"
/* 7: 73, 10 */ "Bus error\0"
/* 8: 83, 25 */ "Floating point exception\0"
/* 9: 108, 7 */ "Killed\0"
/* 10: 115, 22 */ "User defined signal 1\0"
/* 11: 137, 19 */ "Segmentation fault\0"
/* 12: 156, 22 */ "User defined signal 2\0"
/* 13: 178, 12 */ "Broken pipe\0"
/* 14: 190, 12 */ "Alarm clock\0"
/* 15: 202, 11 */ "Terminated\0"
/* 16: 213, 12 */ "Stack fault\0"
/* 17: 225, 13 */ "Child exited\0"
/* 18: 238, 10 */ "Continued\0"
/* 19: 248, 17 */ "Stopped (signal)\0"
/* 20: 265, 8 */ "Stopped\0"
/* 21: 273, 20 */ "Stopped (tty input)\0"
/* 22: 293, 21 */ "Stopped (tty output)\0"
/* 23: 314, 21 */ "Urgent I/O condition\0"
/* 24: 335, 24 */ "CPU time limit exceeded\0"
/* 25: 359, 25 */ "File size limit exceeded\0"
/* 26: 384, 22 */ "Virtual timer expired\0"
/* 27: 406, 24 */ "Profiling timer expired\0"
/* 28: 430, 15 */ "Window changed\0"
/* 29: 445, 13 */ "I/O possible\0"
/* 30: 458, 14 */ "Power failure\0"
/* 31: 472, 16 */ "Bad system call"
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
/* 32: 488, 9 */ "\0EMT trap"
#endif
};
 
#endif
 
/**********************************************************************/
#if defined(L_sys_siglist) && defined(__UCLIBC_HAS_SYS_SIGLIST__)
 
const char *const sys_siglist[_NSIG] = {
[0] = NULL,
[SIGHUP] = _string_syssigmsgs + 1,
[SIGINT] = _string_syssigmsgs + 8,
[SIGQUIT] = _string_syssigmsgs + 18,
[SIGILL] = _string_syssigmsgs + 23,
[SIGTRAP] = _string_syssigmsgs + 43,
[SIGABRT] = _string_syssigmsgs + 65,
[SIGBUS] = _string_syssigmsgs + 73,
[SIGFPE] = _string_syssigmsgs + 83,
[SIGKILL] = _string_syssigmsgs + 108,
[SIGUSR1] = _string_syssigmsgs + 115,
[SIGSEGV] = _string_syssigmsgs + 137,
[SIGUSR2] = _string_syssigmsgs + 156,
[SIGPIPE] = _string_syssigmsgs + 178,
[SIGALRM] = _string_syssigmsgs + 190,
[SIGTERM] = _string_syssigmsgs + 202,
#if !(defined(__alpha__) || defined(__mips__) || defined(__sparc__))
[SIGSTKFLT] = _string_syssigmsgs + 213,
#endif
[SIGCHLD] = _string_syssigmsgs + 225,
[SIGCONT] = _string_syssigmsgs + 238,
[SIGSTOP] = _string_syssigmsgs + 248,
[SIGTSTP] = _string_syssigmsgs + 265,
[SIGTTIN] = _string_syssigmsgs + 273,
[SIGTTOU] = _string_syssigmsgs + 293,
[SIGURG] = _string_syssigmsgs + 314,
[SIGXCPU] = _string_syssigmsgs + 335,
[SIGXFSZ] = _string_syssigmsgs + 359,
[SIGVTALRM] = _string_syssigmsgs + 384,
[SIGPROF] = _string_syssigmsgs + 406,
[SIGWINCH] = _string_syssigmsgs + 430,
[SIGIO] = _string_syssigmsgs + 445,
[SIGPWR] = _string_syssigmsgs + 458,
[SIGSYS] = _string_syssigmsgs + 472,
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
[SIGEMT] = _string_syssigmsgs + 488,
#endif
};
 
#endif
/**********************************************************************/
#ifdef L_strsignal
 
/* TODO: make a threadsafe version? */
 
#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__
 
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
static const unsigned char sstridx[] = {
0,
SIGHUP,
SIGINT,
SIGQUIT,
SIGILL,
SIGTRAP,
SIGIOT,
SIGBUS,
SIGFPE,
SIGKILL,
SIGUSR1,
SIGSEGV,
SIGUSR2,
SIGPIPE,
SIGALRM,
SIGTERM,
#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
0,
#else
SIGSTKFLT,
#endif
SIGCHLD,
SIGCONT,
SIGSTOP,
SIGTSTP,
SIGTTIN,
SIGTTOU,
SIGURG,
SIGXCPU,
SIGXFSZ,
SIGVTALRM,
SIGPROF,
SIGWINCH,
SIGIO,
SIGPWR,
SIGSYS,
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
SIGEMT,
#endif
};
#endif
 
char *strsignal(int signum)
{
register char *s;
int i;
static char buf[_STRSIGNAL_BUFSIZE];
static const char unknown[] = {
'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' '
};
 
#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
/* Need to translate signum to string index. */
for (i = 0 ; i < sizeof(sstridx)/sizeof(sstridx[0]) ; i++) {
if (sstridx[i] == signum) {
goto GOT_SSTRIDX;
}
}
i = INT_MAX; /* Failed. */
GOT_SSTRIDX:
#else
/* No signum to string index translation needed. */
i = signum;
#endif
 
if (((unsigned int) signum) < _SYS_NSIG) {
/* Trade time for space. This function should rarely be called
* so rather than keeping an array of pointers for the different
* messages, just run through the buffer until we find the
* correct string. */
for (s = (char *) _string_syssigmsgs ; i ; ++s) {
if (!*s) {
--i;
}
}
if (*s) { /* Make sure we have an actual message. */
goto DONE;
}
}
 
s = _int10tostr(buf+sizeof(buf)-1, signum) - sizeof(unknown);
memcpy(s, unknown, sizeof(unknown));
 
DONE:
return s;
}
 
#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
 
char *strsignal(int signum)
{
static char buf[_STRSIGNAL_BUFSIZE];
static const char unknown[] = {
'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' '
};
 
return (char *) memcpy(_int10tostr(buf+sizeof(buf)-1, signum)
- sizeof(unknown),
unknown, sizeof(unknown));
}
 
#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
 
#endif
/**********************************************************************/
#ifdef L_psignal
 
/* TODO: make this threadsafe with a reentrant version of strsignal? */
 
void psignal(int signum, register const char *message)
{
/* If the program is calling psignal, it's a safe bet that printf and
* friends are used as well. It is also possible that the calling
* program could buffer stderr, or reassign it. */
 
register const char *sep;
 
sep = ": ";
if (!(message && *message)) { /* Caller did not supply a prefix message */
message = (sep += 2); /* or passed an empty string. */
}
 
#if 1
fprintf(stderr, "%s%s%s\n", message, sep, strsignal(signum));
#else
/* Note: Assumes stderr not closed or buffered. */
__STDIO_THREADLOCK(stderr);
_stdio_fdout(STDERR_FILENO, message, sep, strsignal(signum));
__STDIO_THREADUNLOCK(stderr);
#endif
}
 
#endif
/**********************************************************************/
#ifndef __LOCALE_C_ONLY
#if defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l)
 
#ifdef L_strxfrm
#ifndef WANT_WIDE
#error WANT_WIDE should be defined for L_strxfrm
#endif
#ifdef L_wcsxfrm
#error L_wcsxfrm already defined for L_strxfrm
#endif
#endif /* L_strxfrm */
 
#if defined(L_strxfrm) || defined(L_strxfrm_l)
 
#define wcscoll strcoll
#define wcscoll_l strcoll_l
#define __wcscoll_l __strcoll_l
#define wcsxfrm strxfrm
#define wcsxfrm_l strxfrm_l
#define __wcsxfrm_l __strxfrm_l
 
#undef WANT_WIDE
#undef Wvoid
#undef Wchar
#undef Wuchar
#undef Wint
 
#define Wchar char
 
#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) */
 
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
 
int wcscoll (const Wchar *s0, const Wchar *s1)
{
return __wcscoll_l(s0, s1, __UCLIBC_CURLOCALE );
}
 
size_t wcsxfrm(Wchar *__restrict ws1, const Wchar *__restrict ws2, size_t n)
{
return __wcsxfrm_l(ws1, ws2, n, __UCLIBC_CURLOCALE );
}
 
#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
 
 
#if 0
#define CUR_COLLATE (&__UCLIBC_CURLOCALE_DATA.collate)
#else
#define CUR_COLLATE (& __LOCALE_PTR->collate)
#endif
 
#define MAX_PENDING 8
 
typedef struct {
const Wchar *s;
const Wchar *eob; /* end of backward */
 
__uwchar_t weight;
__uwchar_t ui_weight; /* undefined or invalid */
int colitem;
int weightidx;
int rule;
size_t position;
/* should be wchar_t. if wchar < 0 do EILSEQ? */
__uwchar_t *cip;
__uwchar_t ci_pending[MAX_PENDING]; /* nul-terminated */
 
char *back_buf;
char *bbe; /* end of back_buf (actual last... not 1 past end) */
char *bp; /* ptr into backbuf, NULL if not in backward mode */
char ibb[128];
size_t bb_size;
 
int ru_pushed;
} col_state_t;
 
 
#define WEIGHT_MASK 0x3fffU
#define RULE_MASK 0xc000U
 
#define RULE_FORWARD (1 << 14)
#define RULE_POSITION (1 << 15)
 
#define UI_IDX (WEIGHT_MASK-6)
#define POSIT_IDX (WEIGHT_MASK-5)
#define RANGE_IDX (WEIGHT_MASK-4)
#define UNDEF_IDX (WEIGHT_MASK-3)
#define INVAL_IDX (WEIGHT_MASK-2)
#define DITTO_IDX (WEIGHT_MASK-1)
 
 
#undef TRACE
#if 0
#define TRACE(X) printf X
#else
#define TRACE(X) ((void)0)
#endif
 
static int lookup(wchar_t wc __LOCALE_PARAM )
{
unsigned int sc, n, i0, i1;
 
if (((__uwchar_t) wc) > 0xffffU) {
return 0;
}
 
sc = wc & CUR_COLLATE->ti_mask;
wc >>= CUR_COLLATE->ti_shift;
n = wc & CUR_COLLATE->ii_mask;
wc >>= CUR_COLLATE->ii_shift;
 
i0 = CUR_COLLATE->wcs2colidt_tbl[wc];
i0 <<= CUR_COLLATE->ii_shift;
i1 = CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + i0 + n];
i1 <<= CUR_COLLATE->ti_shift;
return CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + CUR_COLLATE->ti_len + i1 + sc];
 
}
 
static void init_col_state(col_state_t *cs, const Wchar *wcs)
{
memset(cs, 0, sizeof(col_state_t));
cs->s = wcs;
cs->bp = cs->back_buf = cs->ibb;
cs->bb_size = 128;
cs->bbe = cs->back_buf + (cs->bb_size -1);
}
 
static void next_weight(col_state_t *cs, int pass __LOCALE_PARAM )
{
int r, w, ru, ri, popping_backup_stack;
ssize_t n;
const uint16_t *p;
#ifdef WANT_WIDE
#define WC (*cs->s)
#define N (1)
#else /* WANT_WIDE */
wchar_t WC;
size_t n0, nx;
#define N n0
 
#endif /* WANT_WIDE */
 
do {
 
if (cs->ru_pushed) {
ru = cs->ru_pushed;
TRACE(("ru_pushed = %d\n", ru));
cs->ru_pushed = 0;
goto POSITION_SKIP;
}
 
#ifdef __UCLIBC_MJN3_ONLY__
#warning should we walk pendings backwards?
#endif
if (cs->cip) { /* possible pending weight */
if ((r = *(cs->cip++)) == 0) {
cs->cip = NULL;
continue;
}
cs->weightidx = r & WEIGHT_MASK;
assert(cs->weightidx);
/* assert(cs->weightidx != WEIGHT_MASK); */
} else { /* get the next collation item from the string */
TRACE(("clearing popping flag\n"));
popping_backup_stack = 0;
 
IGNORE_LOOP:
/* keep first pos as 0 for a sentinal */
if (*cs->bp) { /* pending backward chars */
POP_BACKUP:
popping_backup_stack = 1;
TRACE(("setting popping flag\n"));
n = 0;
if (*cs->bp > 0) { /* singles pending */
cs->s -= 1;
if ((*cs->bp -= 1) == 0) {
cs->bp -= 1;
}
} else { /* last was a multi */
cs->s += *cs->bp;
cs->bp -= 1;
}
} else if (!*cs->s) { /* not in backward mode and end of string */
cs->weight = 0;
return;
} else {
cs->position += 1;
}
 
BACK_LOOP:
#ifdef WANT_WIDE
n = 1;
cs->colitem = r = lookup(*cs->s __LOCALE_ARG );
#else /* WANT_WIDE */
n = n0 = __locale_mbrtowc_l(&WC, cs->s, __LOCALE_PTR);
if (n < 0) {
__set_errno(EILSEQ);
cs->weight = 0;
return;
}
cs->colitem = r = lookup(WC __LOCALE_ARG );
#endif /* WANT_WIDE */
 
TRACE((" r=%d WC=%#lx\n", r, (unsigned long)(WC)));
 
if (r > CUR_COLLATE->max_col_index) { /* starting char for one or more sequences */
p = CUR_COLLATE->multistart_tbl;
p += p[r-CUR_COLLATE->max_col_index -1];
do {
n = N;
r = *p++;
do {
if (!*p) { /* found it */
cs->colitem = r;
TRACE((" found multi %d\n", n));
goto FOUND;
}
#ifdef WANT_WIDE
/* the lookup check here is safe since we're assured that *p is a valid colidx */
if (!cs->s[n] || (lookup(cs->s[n] __LOCALE_ARG ) != *p)) {
do {} while (*p++);
break;
}
++p;
++n;
#else /* WANT_WIDE */
if (cs->s[n]) {
nx = __locale_mbrtowc_l(&WC, cs->s + n, __LOCALE_PTR);
if (nx < 0) {
__set_errno(EILSEQ);
cs->weight = 0;
return;
}
}
if (!cs->s[n] || (lookup(WC __LOCALE_ARG ) != *p)) {
do {} while (*p++);
break;
}
++p;
n += nx; /* Only gets here if cs->s[n] != 0, so nx is set. */
#endif /* WANT_WIDE */
} while (1);
} while (1);
} else if (r == 0) { /* illegal, undefined, or part of a range */
if ((CUR_COLLATE->range_count)
#ifdef __UCLIBC_MJN3_ONLY__
#warning .. need to introduce range as a collating item?
#endif
&& (((__uwchar_t)(WC - CUR_COLLATE->range_low)) <= CUR_COLLATE->range_count)
) { /* part of a range */
/* Note: cs->colitem = 0 already. */
TRACE((" found range\n"));
ru = CUR_COLLATE->ruletable[CUR_COLLATE->range_rule_offset*CUR_COLLATE->MAX_WEIGHTS + pass];
assert((ru & WEIGHT_MASK) != DITTO_IDX);
if ((ru & WEIGHT_MASK) == WEIGHT_MASK) {
ru = (ru & RULE_MASK) | RANGE_IDX;
cs->weight = CUR_COLLATE->range_base_weight + (WC - CUR_COLLATE->range_low);
}
goto RANGE_SKIP_TO;
} else if (((__uwchar_t)(WC)) <= 0x7fffffffUL) { /* legal but undefined */
UNDEFINED:
/* Note: cs->colitem = 0 already. */
ri = CUR_COLLATE->undefined_idx;
assert(ri != 0); /* implicit undefined isn't supported */
 
TRACE((" found explicit UNDEFINED\n"));
#ifdef __UCLIBC_MJN3_ONLY__
#warning right now single weight locales do not support ..
#endif
if (CUR_COLLATE->num_weights == 1) {
TRACE((" single weight UNDEFINED\n"));
cs->weightidx = RANGE_IDX;
cs->weight = ri;
cs->s += n;
goto PROCESS_WEIGHT;
}
 
ri = CUR_COLLATE->index2ruleidx[ri - 1];
ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass];
assert((ru & WEIGHT_MASK) != WEIGHT_MASK); /* TODO: handle ".." */
if ((ru & WEIGHT_MASK) == DITTO_IDX) {
cs->colitem = CUR_COLLATE->undefined_idx;
}
goto RANGE_SKIP_TO;
} else { /* illegal */
TRACE((" found illegal\n"));
__set_errno(EINVAL);
/* We put all illegals in the same equiv class with maximal weight,
* and ignore them after the first pass. */
if (pass > 0) {
cs->s += n;
goto IGNORE_LOOP;
}
ru = (RULE_FORWARD | RANGE_IDX);
cs->weight = 0xffffU;
goto RANGE_SKIP_TO;
}
} else if (CUR_COLLATE->num_weights == 1) {
TRACE((" single weight\n"));
cs->weightidx = RANGE_IDX;
cs->weight = cs->colitem;
cs->s += n;
goto PROCESS_WEIGHT;
} else {
TRACE((" normal\n"));
}
 
/* if we get here, it is a normal char either singlely weighted, undefined, or in a range */
FOUND:
ri = CUR_COLLATE->index2ruleidx[cs->colitem - 1];
TRACE((" ri=%d ", ri));
#ifdef __UCLIBC_MJN3_ONLY__
#warning make sure this is correct
#endif
if (!ri) {
TRACE(("NOT IN THIS LOCALE\n"));
goto UNDEFINED;
}
ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass];
 
RANGE_SKIP_TO:
 
#ifdef __UCLIBC_MJN3_ONLY__
#warning ignoreables probably should not interrupt backwards processing, but this is wrong
#endif
/* if (!(ru & WEIGHT_MASK)) { */
/* TRACE(("IGNORE\n")); */
/* cs->s += n; */
/* continue; */
/* } */
 
 
TRACE((" rule = %#x weight = %#x popping = %d s = %p eob = %p\n",
ru & RULE_MASK, ru & WEIGHT_MASK, popping_backup_stack,
cs->s, cs->eob));
/* now we need to check if we're going backwards... */
 
if (!popping_backup_stack) {
if (!(ru & RULE_MASK)) { /* backward */
TRACE(("backwards\n"));
assert(cs->bp <= cs->bbe);
if (cs->bp == cs->bbe) {
if (cs->back_buf == cs->ibb) { /* was using internal buffer */
cs->bp = malloc(cs->bb_size + 128);
if (!cs->bp) {
__set_errno(ENOMEM);
#ifdef __UCLIBC_MJN3_ONLY__
#warning what to do here?
#endif
cs->weight = 0;
return;
}
memcpy(cs->bp, cs->back_buf, cs->bb_size);
 
} else {
cs->bp = realloc(cs->back_buf, cs->bb_size + 128);
if (!cs->bp) {
__set_errno(ENOMEM);
#ifdef __UCLIBC_MJN3_ONLY__
#warning what to do here?
#endif
cs->weight = 0;
return;
}
}
cs->bb_size += 128;
cs->bbe = cs->bp + (cs->bbe - cs->back_buf);
cs->back_buf = cs->bp;
cs->bp = cs->bbe;
 
}
if (n==1) { /* single char */
if (*cs->bp && (((unsigned char)(*cs->bp)) < CHAR_MAX)) {
*cs->bp += 1; /* increment last single's count */
} else { /* last was a multi, or just starting */
if (!cs->bp) {
cs->bp = cs->back_buf;
} else {
assert(cs->bp < cs->bbe);
++cs->bp;
}
*cs->bp = 1;
}
} else { /* multichar */
assert(n>1);
assert(cs->bp < cs->bbe);
*++cs->bp = -n;
}
cs->s += n;
if (*cs->s) {
goto BACK_LOOP;
}
/* end-of-string so start popping */
cs->eob = cs->s;
TRACE(("popping\n"));
goto POP_BACKUP;
} else if (*cs->bp) { /* was going backward but this element isn't */
/* discard current and use previous backward element */
assert(!cs->cip);
cs->eob = cs->s;
TRACE(("popping\n"));
goto POP_BACKUP;
} else { /* was and still going forward */
TRACE(("forwards\n"));
if ((ru & (RULE_POSITION|WEIGHT_MASK)) > RULE_POSITION) {
assert(ru & WEIGHT_MASK);
cs->ru_pushed = ru;
cs->weight = cs->position;
#ifdef __UCLIBC_MJN3_ONLY__
#warning devel code
#endif
cs->position = 0; /* reset to reduce size for strcoll? */
cs->s += n;
cs->weightidx = RANGE_IDX;
goto PROCESS_WEIGHT;
}
}
} else { /* popping backwards stack */
TRACE(("popping (continued)\n"));
if (!*cs->bp) {
cs->s = cs->eob;
}
cs->s -= n;
}
 
cs->s += n;
POSITION_SKIP:
cs->weightidx = ru & WEIGHT_MASK;
cs->rule = ru & RULE_MASK;
}
 
#ifdef __UCLIBC_MJN3_ONLY__
#warning for pending we only want the weight... _not_ the rule
#endif
if (!cs->weightidx) { /* ignore */
continue;
}
 
PROCESS_WEIGHT:
assert(cs->weightidx);
 
 
if (((unsigned int)(cs->weightidx - UI_IDX)) <= (INVAL_IDX-UI_IDX)) {
if (cs->weightidx == UI_IDX) {
cs->weight = cs->ui_weight;
}
return;
}
 
assert(cs->weightidx != WEIGHT_MASK);
if (cs->weightidx == DITTO_IDX) { /* want the weight of the current collating item */
TRACE(("doing ditto\n"));
w = CUR_COLLATE->index2weight[cs->colitem -1];
} else if (cs->weightidx <= CUR_COLLATE->max_col_index) { /* normal */
TRACE(("doing normal\n"));
w = CUR_COLLATE->index2weight[cs->weightidx -1];
} else { /* a string */
TRACE(("doing string\n"));
assert(!(cs->weightidx & RULE_MASK));
/* note: iso14561 allows null string here */
p = CUR_COLLATE->weightstr + (cs->weightidx - (CUR_COLLATE->max_col_index + 2));
if (*p & WEIGHT_MASK) {
r = 0;
do {
assert(r < MAX_PENDING);
cs->ci_pending[r++] = *p++;
} while (*p & WEIGHT_MASK);
cs->cip = cs->ci_pending;
}
continue;
}
 
cs->weight = w;
return;
} while (1);
}
 
int __XL(wcscoll) (const Wchar *s0, const Wchar *s1 __LOCALE_PARAM )
{
col_state_t ws[2];
int pass;
 
if (!CUR_COLLATE->num_weights) { /* C locale */
#ifdef WANT_WIDE
return wcscmp(s0, s1);
#else /* WANT_WIDE */
return strcmp(s0, s1);
#endif /* WANT_WIDE */
}
 
pass = 0;
do { /* loop through the weights levels */
init_col_state(ws, s0);
init_col_state(ws+1, s1);
do { /* loop through the strings */
/* for each string, get the next weight */
next_weight(ws, pass __LOCALE_ARG );
next_weight(ws+1, pass __LOCALE_ARG );
TRACE(("w0=%lu w1=%lu\n",
(unsigned long) ws[0].weight,
(unsigned long) ws[1].weight));
 
if (ws[0].weight != ws[1].weight) {
return ws[0].weight - ws[1].weight;
}
} while (ws[0].weight);
} while (++pass < CUR_COLLATE->num_weights);
 
return 0;
}
 
__XL_ALIAS(wcscoll)
 
#ifdef WANT_WIDE
 
size_t __XL(wcsxfrm)(wchar_t *__restrict ws1, const wchar_t *__restrict ws2,
size_t n __LOCALE_PARAM )
{
col_state_t cs;
size_t count;
int pass;
 
if (!CUR_COLLATE->num_weights) { /* C locale */
return __wcslcpy(ws1, ws2, n);
}
 
#ifdef __UCLIBC_MJN3_ONLY__
#warning handle empty string as a special case
#endif
 
count = pass = 0;
do { /* loop through the weights levels */
init_col_state(&cs, ws2);
do { /* loop through the string */
next_weight(&cs, pass __LOCALE_ARG );
TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight));
if (count < n) {
ws1[count] = cs.weight +1;
}
++count;
TRACE(("--------------------------------------------\n"));
} while (cs.weight);
if (count <= n) { /* overwrite the trailing 0 end-of-pass marker */
ws1[count-1] = 1;
}
TRACE(("-------------------- pass %d --------------------\n", pass));
} while (++pass < CUR_COLLATE->num_weights);
if (count <= n) { /* oops... change it back */
ws1[count-1] = 0;
}
return count-1;
}
 
__XL_ALIAS(wcsxfrm)
 
#else /* WANT_WIDE */
 
static const unsigned long bound[] = {
1UL << 7,
1UL << 11,
1UL << 16,
1UL << 21,
1UL << 26,
};
 
static unsigned char first[] = {
0x0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
};
 
/* Use an extension of UTF-8 to store a 32 bit val in max 6 bytes. */
 
static size_t store(unsigned char *s, size_t count, size_t n, __uwchar_t weight)
{
int i, r;
 
i = 0;
do {
if (weight < bound[i]) {
break;
}
} while (++i < sizeof(bound)/sizeof(bound[0]));
 
r = i+1;
if (i + count < n) {
s += count;
s[0] = first[i];
while (i) {
s[i] = 0x80 | (weight & 0x3f);
weight >>= 6;
--i;
}
s[0] |= weight;
}
 
return r;
}
 
size_t __XL(strxfrm)(char *__restrict ws1, const char *__restrict ws2, size_t n
__LOCALE_PARAM )
{
col_state_t cs;
size_t count, inc;
int pass;
 
if (!CUR_COLLATE->num_weights) { /* C locale */
return strlcpy(ws1, ws2, n);
}
 
#ifdef __UCLIBC_MJN3_ONLY__
#warning handle empty string as a special case
#endif
 
inc = count = pass = 0;
do { /* loop through the weights levels */
init_col_state(&cs, ws2);
do { /* loop through the string */
next_weight(&cs, pass __LOCALE_ARG );
TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight));
inc = store((unsigned char *)ws1, count, n, cs.weight + 1);
count += inc;
TRACE(("--------------------------------------------\n"));
} while (cs.weight);
/* overwrite the trailing 0 end-of-pass marker */
assert(inc == 1);
if (count <= n) {
ws1[count-1] = 1;
}
TRACE(("-------------------- pass %d --------------------\n", pass));
} while (++pass < CUR_COLLATE->num_weights);
if (count <= n) { /* oops... change it back */
ws1[count-1] = 0;
}
return count-1;
}
 
__XL_ALIAS(strxfrm)
 
#endif /* WANT_WIDE */
 
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
 
#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l) */
 
#endif /* __LOCALE_C_ONLY */
/**********************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.