first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+385
View File
@@ -0,0 +1,385 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
.text
.align 2
.globl _memcpy
.globl _bcopy
.globl _memmove
_bcopy: /* void bcopy(const void *src, void *dest, size_t len); */
mov r3, r0
mov r0, r1
mov r1, r3
_memcpy: /* void *memcpy(void *dest, const void *src, size_t len); */
_memmove: /* void *memmove(void *dest, const void *src, size_t len); */
/* check for zero len or if the pointers are the same */
cmp r2, #0
cmpne r0, r1
bxeq lr
/* save r0 (return value), r4 (scratch), and r5 (scratch) */
stmfd sp!, { r0, r4, r5 }
/* check for overlap. r3 <- distance between src & dest */
subhs r3, r0, r1
sublo r3, r1, r0
cmp r3, r2 /* if distance(src, dest) < len, we have overlap */
blo Loverlap
Lnormalforwardcopy:
/* are src and dest dissimilarly word aligned? */
mov r12, r0, lsl #30
cmp r12, r1, lsl #30
bne Lnonwordaligned_forward
/* if len < 64, do a quick forward copy */
cmp r2, #64
blt Lsmallforwardcopy
/* check for 16 byte src/dest unalignment */
tst r0, #0xf
bne Lsimilarlyunaligned
/* check for 32 byte dest unalignment */
tst r0, #(1<<4)
bne Lunaligned_32
Lmorethan64_aligned:
/* save some more registers to use in the copy */
stmfd sp!, { r6, r7, r10, r11 }
/* pre-subtract 64 from the len counter to avoid an extra compare in the loop */
sub r2, r2, #64
L64loop:
/* copy 64 bytes at a time */
ldmia r1!, { r3, r4, r5, r6, r7, r10, r11, r12 }
#if ARCH_ARMv7
pld [r1, #32]
#endif
stmia r0!, { r3, r4, r5, r6, r7, r10, r11, r12 }
ldmia r1!, { r3, r4, r5, r6, r7, r10, r11, r12 }
subs r2, r2, #64
#if ARCH_ARMv7
pld [r1, #32]
#endif
stmia r0!, { r3, r4, r5, r6, r7, r10, r11, r12 }
bge L64loop
/* restore the scratch registers we just saved */
ldmfd sp!, { r6, r7, r10, r11 }
/* fix up the len counter (previously subtracted an extra 64 from it) and test for completion */
adds r2, r2, #64
beq Lexit
Llessthan64_aligned:
/* copy 16 bytes at a time until we have < 16 bytes */
cmp r2, #16
ldmiage r1!, { r3, r4, r5, r12 }
stmiage r0!, { r3, r4, r5, r12 }
subsge r2, r2, #16
bgt Llessthan64_aligned
beq Lexit
Llessthan16_aligned:
mov r2, r2, lsl #28
msr cpsr_f, r2
ldmiami r1!, { r2, r3 }
ldreq r4, [r1], #4
ldrhcs r5, [r1], #2
ldrbvs r12, [r1], #1
stmiami r0!, { r2, r3 }
streq r4, [r0], #4
strhcs r5, [r0], #2
strbvs r12, [r0], #1
b Lexit
Lsimilarlyunaligned:
/* both src and dest are unaligned in similar ways, align to dest on 32 byte boundary */
mov r12, r0, lsl #28
rsb r12, r12, #0
msr cpsr_f, r12
ldrbvs r3, [r1], #1
ldrhcs r4, [r1], #2
ldreq r5, [r1], #4
strbvs r3, [r0], #1
strhcs r4, [r0], #2
streq r5, [r0], #4
ldmiami r1!, { r3, r4 }
stmiami r0!, { r3, r4 }
subs r2, r2, r12, lsr #28
beq Lexit
Lunaligned_32:
/* bring up to dest 32 byte alignment */
tst r0, #(1 << 4)
ldmiane r1!, { r3, r4, r5, r12 }
stmiane r0!, { r3, r4, r5, r12 }
subne r2, r2, #16
/* we should now be aligned, see what copy method we should use */
cmp r2, #64
bge Lmorethan64_aligned
b Llessthan64_aligned
Lbytewise2:
/* copy 2 bytes at a time */
subs r2, r2, #2
ldrb r3, [r1], #1
ldrbpl r4, [r1], #1
strb r3, [r0], #1
strbpl r4, [r0], #1
bhi Lbytewise2
b Lexit
Lbytewise:
/* simple bytewise forward copy */
ldrb r3, [r1], #1
subs r2, r2, #1
strb r3, [r0], #1
bne Lbytewise
b Lexit
Lsmallforwardcopy:
/* src and dest are word aligned similarly, less than 64 bytes to copy */
cmp r2, #4
blt Lbytewise2
/* bytewise copy until word aligned */
tst r1, #3
Lwordalignloop:
ldrbne r3, [r1], #1
strbne r3, [r0], #1
subne r2, r2, #1
tstne r1, #3
bne Lwordalignloop
cmp r2, #16
bge Llessthan64_aligned
blt Llessthan16_aligned
Loverlap:
/* src and dest overlap in some way, len > 0 */
cmp r0, r1 /* if dest > src */
bhi Loverlap_srclower
Loverlap_destlower:
/* dest < src, see if we can still do a fast forward copy or fallback to slow forward copy */
cmp r3, #64
bge Lnormalforwardcopy /* overlap is greater than one stride of the copy, use normal copy */
cmp r3, #2
bge Lbytewise2
b Lbytewise
/* the following routines deal with having to copy in the reverse direction */
Loverlap_srclower:
/* src < dest, with overlap */
/* src += len; dest += len; */
add r0, r0, r2
add r1, r1, r2
/* we have to copy in reverse no matter what, test if we can we use a large block reverse copy */
cmp r2, #64 /* less than 64 bytes to copy? */
cmpgt r3, #64 /* less than 64 bytes of nonoverlap? */
blt Lbytewise_reverse
/* test of src and dest are nonword aligned differently */
mov r3, r0, lsl #30
cmp r3, r1, lsl #30
bne Lbytewise_reverse
/* test if src and dest are non word aligned or dest is non 16 byte aligned */
tst r0, #0xf
bne Lunaligned_reverse_similarly
/* test for dest 32 byte alignment */
tst r0, #(1<<4)
bne Lunaligned_32_reverse_similarly
/* 64 byte reverse block copy, src and dest aligned */
Lmorethan64_aligned_reverse:
/* save some more registers to use in the copy */
stmfd sp!, { r6, r7, r10, r11 }
/* pre-subtract 64 from the len counter to avoid an extra compare in the loop */
sub r2, r2, #64
L64loop_reverse:
/* copy 64 bytes at a time */
ldmdb r1!, { r3, r4, r5, r6, r7, r10, r11, r12 }
#if ARCH_ARMv7
pld [r1, #-32]
#endif
stmdb r0!, { r3, r4, r5, r6, r7, r10, r11, r12 }
ldmdb r1!, { r3, r4, r5, r6, r7, r10, r11, r12 }
subs r2, r2, #64
#if ARCH_ARMv7
pld [r1, #-32]
#endif
stmdb r0!, { r3, r4, r5, r6, r7, r10, r11, r12 }
bge L64loop_reverse
/* restore the scratch registers we just saved */
ldmfd sp!, { r6, r7, r10, r11 }
/* fix up the len counter (previously subtracted an extra 64 from it) and test for completion */
adds r2, r2, #64
beq Lexit
Lbytewise_reverse:
ldrb r3, [r1, #-1]!
strb r3, [r0, #-1]!
subs r2, r2, #1
bne Lbytewise_reverse
b Lexit
Lunaligned_reverse_similarly:
/* both src and dest are unaligned in similar ways, align to dest on 32 byte boundary */
mov r12, r0, lsl #28
msr cpsr_f, r12
ldrbvs r3, [r1, #-1]!
ldrhcs r4, [r1, #-2]!
ldreq r5, [r1, #-4]!
strbvs r3, [r0, #-1]!
strhcs r4, [r0, #-2]!
streq r5, [r0, #-4]!
ldmdbmi r1!, { r3, r4 }
stmdbmi r0!, { r3, r4 }
subs r2, r2, r12, lsr #28
beq Lexit
Lunaligned_32_reverse_similarly:
/* bring up to dest 32 byte alignment */
tst r0, #(1 << 4)
ldmdbne r1!, { r3, r4, r5, r12 }
stmdbne r0!, { r3, r4, r5, r12 }
subne r2, r2, #16
/* we should now be aligned, see what copy method we should use */
cmp r2, #64
bge Lmorethan64_aligned_reverse
b Lbytewise_reverse
/* the following routines deal with non word aligned copies */
Lnonwordaligned_forward:
cmp r2, #8
blt Lbytewise2 /* not worth the effort with less than 24 bytes total */
/* bytewise copy until src word aligned */
tst r1, #3
Lwordalignloop2:
ldrbne r3, [r1], #1
strbne r3, [r0], #1
subne r2, r2, #1
tstne r1, #3
bne Lwordalignloop2
/* figure out how the src and dest are unaligned */
and r3, r0, #3
cmp r3, #2
blt Lalign1_forward
beq Lalign2_forward
bgt Lalign3_forward
Lalign1_forward:
/* the dest pointer is 1 byte off from src */
mov r12, r2, lsr #2 /* number of words we should copy */
sub r0, r0, #1
/* prime the copy */
ldrb r4, [r0] /* load D[7:0] */
Lalign1_forward_loop:
ldr r3, [r1], #4 /* load S */
orr r4, r4, r3, lsl #8 /* D[31:8] = S[24:0] */
str r4, [r0], #4 /* save D */
mov r4, r3, lsr #24 /* D[7:0] = S[31:25] */
subs r12, r12, #1
bne Lalign1_forward_loop
/* finish the copy off */
strb r4, [r0], #1 /* save D[7:0] */
ands r2, r2, #3
beq Lexit
b Lbytewise2
Lalign2_forward:
/* the dest pointer is 2 bytes off from src */
mov r12, r2, lsr #2 /* number of words we should copy */
sub r0, r0, #2
/* prime the copy */
ldrh r4, [r0] /* load D[15:0] */
Lalign2_forward_loop:
ldr r3, [r1], #4 /* load S */
orr r4, r4, r3, lsl #16 /* D[31:16] = S[15:0] */
str r4, [r0], #4 /* save D */
mov r4, r3, lsr #16 /* D[15:0] = S[31:15] */
subs r12, r12, #1
bne Lalign2_forward_loop
/* finish the copy off */
strh r4, [r0], #2 /* save D[15:0] */
ands r2, r2, #3
beq Lexit
b Lbytewise2
Lalign3_forward:
/* the dest pointer is 3 bytes off from src */
mov r12, r2, lsr #2 /* number of words we should copy */
sub r0, r0, #3
/* prime the copy */
ldr r4, [r0]
and r4, r4, #0x00ffffff /* load D[24:0] */
Lalign3_forward_loop:
ldr r3, [r1], #4 /* load S */
orr r4, r4, r3, lsl #24 /* D[31:25] = S[7:0] */
str r4, [r0], #4 /* save D */
mov r4, r3, lsr #8 /* D[24:0] = S[31:8] */
subs r12, r12, #1
bne Lalign3_forward_loop
/* finish the copy off */
strh r4, [r0], #2 /* save D[15:0] */
mov r4, r4, lsr #16
strb r4, [r0], #1 /* save D[23:16] */
ands r2, r2, #3
beq Lexit
b Lbytewise2
Lexit:
ldmfd sp!, { r0, r4, r5 }
bx lr
+145
View File
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
/*
* A reasonably well-optimized bzero/memset. Should work equally well on arm11 and arm9 based
* cores.
*
* The algorithm is to align the destination pointer on a 32 byte boundary and then
* blast data 64 bytes at a time, in two stores of 32 bytes per loop.
*/
.text
.align 2
.globl _memset
/* void *memset(void *ptr, int c, size_t len); */
_memset:
/* move len into r1, unpack c into r2 */
mov r3, r2
and r1, r1, #0xff
orr r1, r1, r1, lsl #8
orr r2, r1, r1, lsl #16
mov r1, r3
b Lbzeroengine
.globl _bzero
/* void bzero(void *ptr, size_t len); */
_bzero:
/* zero out r2 so we can be just like memset(0) */
mov r2, #0
Lbzeroengine:
/* move the base pointer into r12 and leave r0 alone so that we return the original pointer */
mov r12, r0
/* copy r2 into r3 for 64-bit stores */
mov r3, r2
/* check for zero len */
cmp r1, #0
bxeq lr
/* fall back to a bytewise store for less than 32 bytes */
cmp r1, #32
blt L_bytewise
/* check for 32 byte unaligned ptr */
tst r12, #0x1f
bne L_unaligned
/* make sure we have more than 64 bytes to zero */
cmp r1, #64
blt L_lessthan64aligned
/* >= 64 bytes of len, 32 byte aligned */
L_64ormorealigned:
/* we need some registers, avoid r9 */
stmfd sp!, { r4-r8, r10 }
mov r4, r2
mov r5, r2
mov r6, r2
mov r7, r2
mov r8, r2
mov r10, r2
/* pre-subtract 64 from the len to avoid an extra compare in the loop */
sub r1, r1, #64
L_64loop:
stmia r12!, { r2-r8, r10 }
subs r1, r1, #64
stmia r12!, { r2-r8, r10 }
bge L_64loop
/* restore the saved regs */
ldmfd sp!, { r4-r8, r10 }
/* check for completion (had previously subtracted an extra 64 from len) */
adds r1, r1, #64
bxeq lr
L_lessthan64aligned:
/* do we have 16 or more bytes left */
cmp r1, #16
stmiage r12!, { r2-r3 }
stmiage r12!, { r2-r3 }
subsge r1, r1, #16
bgt L_lessthan64aligned
bxeq lr
L_lessthan16aligned:
/* store 0 to 15 bytes */
mov r1, r1, lsl #28 /* move the remaining len bits [3:0] to the flags area of cpsr */
msr cpsr_f, r1
stmiami r12!, { r2-r3 } /* n is set, store 8 bytes */
streq r2, [r12], #4 /* z is set, store 4 bytes */
strhcs r2, [r12], #2 /* c is set, store 2 bytes */
strbvs r2, [r12], #1 /* v is set, store 1 byte */
bx lr
L_bytewise:
/* bytewise copy, 2 bytes at a time, alignment not guaranteed */
subs r1, r1, #2
strb r2, [r12], #1
strbpl r2, [r12], #1
bhi L_bytewise
bx lr
L_unaligned:
/* unaligned on 32 byte boundary, store 1-15 bytes until we're 16 byte aligned */
mov r3, r12, lsl #28
rsb r3, r3, #0x00000000
msr cpsr_f, r3
strbvs r2, [r12], #1 /* v is set, unaligned in the 1s column */
strhcs r2, [r12], #2 /* c is set, unaligned in the 2s column */
streq r2, [r12], #4 /* z is set, unaligned in the 4s column */
strmi r2, [r12], #4 /* n is set, unaligned in the 8s column */
strmi r2, [r12], #4
subs r1, r1, r3, lsr #28
bxeq lr
/* we had previously trashed r3, restore it */
mov r3, r2
/* now make sure we're 32 byte aligned */
tst r12, #(1 << 4)
stmiane r12!, { r2-r3 }
stmiane r12!, { r2-r3 }
subsne r1, r1, #16
/* we're now aligned, check for >= 64 bytes left */
cmp r1, #64
bge L_64ormorealigned
b L_lessthan64aligned
+24
View File
@@ -0,0 +1,24 @@
# Copyright (C) 2007-2009 Apple Inc. All rights reserved.
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
LIBC_OBJS += \
$(LOCAL_DIR)/bcopy.o \
$(LOCAL_DIR)/bzero.o \
$(LOCAL_DIR)/strlen.o
ARCH_STROPS := \
bcopy \
bzero \
memset \
memmove \
memcpy \
strlen
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
.text
.align 2
.globl _strlen
/* int strlen(const char *s); */
_strlen:
/* save the original pointer */
mov r12, r0
/* see if the string is aligned */
ands r3, r0, #3
/* load the first word, address rounded down */
bic r0, r0, #3
ldr r2, [r0], #4
/* skip the next part if the string is already aligned */
beq Laligned
Lunaligned:
/* unaligned pointer, mask out the bytes that we've read that we should be ignoring */
cmp r3, #2
orr r2, r2, #0x000000ff
orrge r2, r2, #0x0000ff00
orrgt r2, r2, #0x00ff0000
Laligned:
/* load 0x01010101 into r1 */
mov r1, #0x01
orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16
Laligned_loop:
/* ((x - 0x01010101) & ~x & 0x80808080) == hasnull(word) */
sub r3, r2, r1 /* x - 0x01010101 */
bic r3, r3, r2 /* above & ~x */
tst r3, r1, lsl #7 /* above & 0x80808080 */
ldreq r2, [r0], #4 /* load next word */
beq Laligned_loop
/* we found a nullbyte */
/* r0 (ptr) has overshot by up to 4 bytes, so subtract off until we find a nullbyte */
sub r0, r0, #1
tst r2, #0x000000ff
subeq r0, r0, #1
tstne r2, #0x0000ff00
subeq r0, r0, #1
tstne r2, #0x00ff0000
subeq r0, r0, #1
Lexit:
/* len = ptr - original pointer */
sub r0, r0, r12
bx lr
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2007 Apple Inc. All rights reserved.
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#ifndef _ARM_ASM_H_
#define _ARM_ASM_H_
#ifdef __ASSEMBLER__
#define PUSH_FRAME \
stp fp, lr, [sp, #-16]! %% \
mov fp, sp %%
#define POP_FRAME \
mov sp, fp %% \
ldp fp, lr, [sp], #16 %%
#endif /* __ASSEMBLER__ */
#endif /* _ARM_ASM_H_ */
+294
View File
@@ -0,0 +1,294 @@
/*
* Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*
* This file implements the following functions for the arm64 architecture.
*
* void bcopy(const void * source,
* void * destination,
* size_t length);
*
* void *memmove(void * destination,
* const void * source,
* size_t n);
*
* void *memcpy(void * restrict destination,
* const void * restrict source,
* size_t n);
*
* All copy n successive bytes from source to destination. Memmove and memcpy
* return destination, whereas bcopy has no return value. Copying takes place
* as if it were through a temporary buffer -- after return destination
* contains exactly the bytes from source, even if the buffers overlap (this is
* not required of memcpy by the C standard; its behavior is undefined if the
* buffers overlap, but we are holding ourselves to the historical behavior of
* this function on MacOS).
*/
#include "asm.h"
.globl _bcopy
.globl _memcpy
.globl _memmove
/*****************************************************************************
* Macros *
*****************************************************************************/
#define kSmallCopy 64
/*****************************************************************************
* Entrypoints *
*****************************************************************************/
.text
.align 5
_bcopy:
// Translate bcopy into memcpy by swapping the first and second arguments.
mov x3, x0
mov x0, x1
mov x1, x3
.align 4
_memcpy:
_memmove:
// Our preference is to copy the data in ascending address order, but if the
// buffers overlap such that the beginning of the destination buffer aliases
// the end of the source buffer, we need to copy in descending address order
// instead to preserve the memmove semantics. We detect this case with the
// test:
//
// destination - source < length (unsigned compare)
//
// If the address of the source buffer is higher than the address of the
// destination buffer, this arithmetic can overflow, but the overflowed value
// can only be smaller than length if the buffers do not overlap, so we don't
// need to worry about false positives due to the overflow (they happen, but
// only in cases where copying in either order is correct).
PUSH_FRAME
sub x3, x0, x1
cmp x3, x2
b.cc L_reverse
mov x3, x0 // copy destination pointer
cmp x2, #(kSmallCopy)
b.cc L_forwardSmallCopy
/*****************************************************************************
* Forward large copy *
*****************************************************************************/
// Load the first 32 bytes from src, and compute the number of bytes to the
// first 32-byte aligned location in dst. Even though we are going to copy
// 32 bytes, only those preceeding that 32-byte location "count" towards
// reducing the length of the buffer or advancing the pointers. We will need
// to issue the first load from the advanced src pointer BEFORE the store to
// the unmodified dst pointer.
add x3, x3, #32
and x3, x3, #-32 // aligned dst
ldp x12,x13,[x1]
ldp x14,x15,[x1, #16]
sub x5, x3, x0 // bytes between original dst and aligned dst
add x1, x1, x5 // update src pointer
// At this point, data in the following registers is in flight:
//
// x0 original dst pointer
// x1 corresponding location in src buffer.
// x2 length from aligned location in dst to end of buffer. This is
// guaranteed to be >= (64 - 32).
// x3 aligned location in dst buffer.
// x12:x15 first 32 bytes of src buffer.
//
// We now load 32 bytes from x1, and store 32 bytes from x12:x15 to x3. The
// store *may* overlap the first 32 bytes of the load, so in order to get
// correct memmove semantics, the first 32 byte load must occur before the
// store.
//
// After loading these 32 bytes, we advance x1, and decrement the length by
// 64. If the remaining length of the buffer was less than 64, then we jump
// directly to the cleanup path.
ldp x8, x9, [x1]
ldp x10,x11,[x1, #16]
add x1, x1, #32
sub x2, x2, x5 // update length
stp x12,x13,[x0] // initial unaligned store
stp x14,x15,[x0, #16] // initial unaligned store
subs x2, x2, #64
b.ls L_forwardCleanup
L_forwardCopyLoop:
// Main copy loop:
//
// 1. store the 32 bytes loaded in the previous loop iteration
// 2. advance the destination pointer
// 3. load the next 32 bytes
// 4. advance the source pointer
// 5. subtract 32 from the length
//
// The loop is terminated when 32 or fewer bytes remain to be loaded. Those
// trailing 1-32 bytes will be copied in the loop cleanup.
stnp x8, x9, [x3]
stnp x10,x11,[x3, #16]
add x3, x3, #32
ldnp x8, x9, [x1]
ldnp x10,x11,[x1, #16]
add x1, x1, #32
subs x2, x2, #32
b.hi L_forwardCopyLoop
L_forwardCleanup:
// There are 32 bytes in x8-x11 that were loaded in the previous loop
// iteration, which need to be stored to [x3,x3+32). In addition, between
// 0 and 32 more bytes need to be copied from x1 to x3 + 32. The exact
// number of bytes to copy is x2 + 32. Instead of using smaller conditional
// copies, we simply copy 32 unaligned bytes from x1+x2 to 64+x3+x2.
// This copy may overlap with the first store, so the loads must come before
// the store of the data from the previous loop iteration.
add x1, x1, x2
ldp x12,x13,[x1]
ldp x14,x15,[x1, #16]
stp x8, x9, [x3]
stp x10,x11,[x3, #16]
add x3, x3, x2
stp x12,x13,[x3, #32]
stp x14,x15,[x3, #48]
POP_FRAME
ret
/*****************************************************************************
* forward small copy *
*****************************************************************************/
// Copy one quadword at a time until less than 8 bytes remain to be copied.
// At the point of entry to L_forwardSmallCopy, the "calling convention"
// is as follows:
//
// x0 pointer to first byte of destination
// x1 pointer to first byte of source
// x2 length of buffers
// x3 pointer to first byte of destination
0: ldr x6, [x1],#8
str x6, [x3],#8
L_forwardSmallCopy:
subs x2, x2, #8
b.cs 0b
adds x2, x2, #8
b.eq 2f
1: ldrb w6, [x1],#1
strb w6, [x3],#1
subs x2, x2, #1
b.ne 1b
2: POP_FRAME
ret
/*****************************************************************************
* Reverse copy engines *
*****************************************************************************/
// The reverse copy engines are identical in every way to the forward copy
// engines, except in that they do everything backwards. For this reason, they
// are somewhat more sparsely commented than the forward copy loops. I have
// tried to only comment things that might be somewhat surprising in how they
// differ from the forward implementation.
//
// The one important thing to note is that (almost without fail), x1 and x3
// will point to ONE BYTE BEYOND the "right-hand edge" of the active buffer
// throughout these copy loops. They are initially advanced to that position
// in the L_reverse jump island. Because of this, whereas the forward copy
// loops generally follow a "copy data, then advance pointers" scheme, in the
// reverse copy loops, we advance the pointers, then copy the data.
L_reverse:
// As a minor optimization, we early out if dst == src.
cbz x3, L_return
// advance both pointers to the ends of their respective buffers before
// jumping into the appropriate reverse copy loop.
add x4, x0, x2
add x1, x1, x2
cmp x2, #(kSmallCopy)
b.cc L_reverseSmallCopy
/*****************************************************************************
* Reverse large copy *
*****************************************************************************/
ldp x12,x13,[x1, #-16]
ldp x14,x15,[x1, #-32]
sub x3, x4, #1 // In the forward copy, we used dst+32 & -32
and x3, x3, #-32 // to find an aligned location in the dest
sub x5, x4, x3 // buffer. Here we use dst-1 & -32 instead,
sub x1, x1, x5 // because we are going backwards.
sub x2, x2, x5
ldp x8, x9, [x1, #-16]
ldp x10,x11,[x1, #-32]
stp x12,x13,[x4, #-16]
stp x14,x15,[x4, #-32]
sub x1, x1, #32
subs x2, x2, #64
b.ls L_reverseCleanup
L_reverseCopyLoop:
stnp x8, x9, [x3, #-16]
stnp x10,x11,[x3, #-32]
sub x3, x3, #32
ldnp x8, x9, [x1, #-16]
ldnp x10,x11,[x1, #-32]
sub x1, x1, #32
subs x2, x2, #32
b.hi L_reverseCopyLoop
L_reverseCleanup:
sub x1, x1, x2
ldp x12,x13,[x1, #-16]
ldp x14,x15,[x1, #-32]
stp x8, x9, [x3, #-16]
stp x10,x11,[x3, #-32]
stp x12,x13,[x0, #16] // In the forward copy, we need to compute the
stp x14,x15,[x0] // address of these stores, but here we already
POP_FRAME // have a pointer to the start of the buffer.
ret
/*****************************************************************************
* reverse small copy *
*****************************************************************************/
0: ldr x6, [x1,#-8]!
str x6, [x4,#-8]!
L_reverseSmallCopy:
subs x2, x2, #8
b.cs 0b
adds x2, x2, #8
b.eq 2f
1: ldrb w6, [x1,#-1]!
strb w6, [x4,#-1]!
subs x2, x2, #1
b.ne 1b
2: POP_FRAME
ret
L_return:
POP_FRAME
ret
+147
View File
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*
* This file implements the following functions for the arm64 architecture:
*
* void bzero(void *buffer, size_t length);
* void __bzero(void *buffer, size_t length);
* void *memset(void *buffer, int value, size_t length);
*
* The first two zero-fill a buffer. The third fills the buffer with the low
* byte of its second argument.
*/
#include "asm.h"
.globl _bzero
.globl ___bzero
.globl _memset
/*****************************************************************************
* bzero entrypoint *
*****************************************************************************/
.text
.align 4
_bzero:
___bzero:
PUSH_FRAME
mov x2, x1
eor x1, x1, x1
mov x3, x0
cmp x2, #128
b.cc L_memsetSmall
/*****************************************************************************
* Large buffer zero engine *
*****************************************************************************/
L_bzeroLarge:
// Write the first 64 bytes of the buffer without regard to alignment, then
// advance x3 to point to a cacheline-aligned location within the buffer, and
// decrement the length accordingly.
stp x1, x1, [x0]
stp x1, x1, [x0, #16]
stp x1, x1, [x0, #32]
stp x1, x1, [x0, #48]
add x3, x0, #64
and x3, x3, #-64
add x2, x2, x0 // end of buffer
add x4, x3, #64 // end of first cacheline to zero
subs x2, x2, x4 // if the end of the buffer comes first, jump
b.ls 1f // directly to the cleanup pass.
0: dc zva, x3 // zero cacheline
add x3, x3, #64 // increment pointer
subs x2, x2, #64 // decrement length
b.hi 0b
1: add x3, x3, x2 // back up pointer to (end of buffer) - 64.
stp x1, x1, [x3] // and store 64 bytes to reach end of buffer.
stp x1, x1, [x3, #16]
stp x1, x1, [x3, #32]
stp x1, x1, [x3, #48]
POP_FRAME
ret
/*****************************************************************************
* memset entrypoint *
*****************************************************************************/
.align 4
_memset:
PUSH_FRAME
and x1, x1, #0xff
orr x3, xzr,#0x0101010101010101
mul x1, x1, x3
mov x3, x0
cmp x2, #64
b.cc L_memsetSmall
/*****************************************************************************
* Large buffer store engine *
*****************************************************************************/
L_memsetLarge:
// Write the first 64 bytes of the buffer without regard to alignment, then
// advance x3 to point to an aligned location within the buffer, and
// decrement the length accordingly.
stp x1, x1, [x0]
add x3, x0, #16
and x3, x3, #-16
add x2, x2, x0 // end of buffer
add x4, x3, #64 // end of first aligned 64-byte store
subs x2, x2, x4 // if the end of the buffer comes first, jump
b.ls 1f // directly to the cleanup store.
0: stnp x1, x1, [x3]
stnp x1, x1, [x3, #16]
stnp x1, x1, [x3, #32]
stnp x1, x1, [x3, #48]
add x3, x3, #64
subs x2, x2, #64
b.hi 0b
1: add x3, x3, x2 // back up pointer to (end of buffer) - 64.
stp x1, x1, [x3]
stp x1, x1, [x3, #16]
stp x1, x1, [x3, #32]
stp x1, x1, [x3, #48]
POP_FRAME
ret
/*****************************************************************************
* Small buffer store engine *
*****************************************************************************/
0: str x1, [x3],#8
L_memsetSmall:
subs x2, x2, #8
b.cs 0b
adds x2, x2, #8
b.eq 2f
1: strb w1, [x3],#1
subs x2, x2, #1
b.ne 1b
2: POP_FRAME
ret
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2012 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
/* void memcpy_16(uint8_t *dest, const void * src, size_t count); */
.text
.align 2
.globl _memcpy_16
_memcpy_16:
mov x3, x0
mov x4, x1
L__memcpy_16_loop:
ldp x5, x6, [x4], #16
stp x5, x6, [x3], #16
subs x2, x2, #16
b.ne L__memcpy_16_loop
ret
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2012 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
/* void memset_16(uint8_t *ptr, uint8_t c, size_t count); */
.text
.align 2
.globl _memset_16
_memset_16:
mov x3, x0
cbz x1, L__memset_16_loop
orr x1, x1, x1, lsl #8
orr x1, x1, x1, lsl #16
orr x1, x1, x1, lsl #32
L__memset_16_loop:
stp x1, x1, [x3], #16
subs x2, x2, #16
b.gt L__memset_16_loop
ret
/* void bzero_64(uint8_t *ptr, size_t count); */
.text
.align 2
.globl _bzero_64
_bzero_64:
mov x2, x0
L__bzero_64_loop:
dc zva, x2
add x2, x2, #64
subs x1, x1, #64
b.gt L__bzero_64_loop
ret
+21
View File
@@ -0,0 +1,21 @@
# Copyright (C) 2011-2012 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
LIBC_OBJS += \
$(LOCAL_DIR)/bcopy.o \
$(LOCAL_DIR)/bzero.o
ARCH_STROPS := \
bcopy \
bzero \
memset \
memmove \
memcpy
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <stdlib.h>
int
atoi(str)
const char *str;
{
return (int)strtol(str, (char **)NULL, 10);
}
+128
View File
@@ -0,0 +1,128 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <ctype.h>
#define _U 0x01 /* upper */
#define _L 0x02 /* lower */
#define _D 0x04 /* digit */
#define _C 0x08 /* cntrl */
#define _P 0x10 /* punct */
#define _S 0x20 /* white space (space/lf/tab) */
#define _X 0x40 /* hex digit */
#define _SP 0x80 /* hard space (0x20) */
#define ismask(x) (_ctype[(int)(unsigned char)(x)])
static unsigned char _ctype[] = {
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
unsigned char tolower(unsigned char c)
{
if(isupper(c))
c -= 'A'-'a';
return c;
}
unsigned char toupper(unsigned char c)
{
if(islower(c))
c -= 'a'-'A';
return c;
}
int isalnum(int c)
{
return ((ismask(c)&(_U|_L|_D)) != 0);
}
int isalpha(int c)
{
return ((ismask(c)&(_U|_L)) != 0);
}
int iscntrl(int c)
{
return ((ismask(c)&(_C)) != 0);
}
int isdigit(int c)
{
return ((ismask(c)&(_D)) != 0);
}
int isgraph(int c)
{
return ((ismask(c)&(_P|_U|_L|_D)) != 0);
}
int islower(int c)
{
return ((ismask(c)&(_L)) != 0);
}
int isprint(int c)
{
return ((ismask(c)&(_P|_U|_L|_D|_SP)) != 0);
}
int ispunct(int c)
{
return ((ismask(c)&(_P)) != 0);
}
int isspace(int c)
{
return ((ismask(c)&(_S)) != 0);
}
int isupper(int c)
{
return ((ismask(c)&(_U)) != 0);
}
int isxdigit(int c)
{
return ((ismask(c)&(_D|_X)) != 0);
}
int isascii(int c)
{
return ((unsigned char)c <= 0x7f);
}
int toascii(int c)
{
return ((unsigned char)c & 0x7f);
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <stdlib.h>
#if ARCH_ARMv7
u_int32_t swap32(u_int32_t x)
{
u_int32_t y;
__asm__ volatile("rev %0, %1" : "=r" (y) : "r" (x));
return y;
}
u_int16_t swap16(u_int16_t x)
{
u_int16_t y;
__asm__ volatile("rev16 %0, %1" : "=r" (y) : "r" (x));
return y;
}
#else
u_int32_t swap32(u_int32_t x)
{
return ((((x) << 24) & 0xff000000) | (((x) << 8) & 0x00ff0000) | (((x) >> 8) & 0x0000ff00) | (((x) >> 24) & 0x000000ff));
}
u_int16_t swap16(u_int16_t x)
{
return ((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff));
}
#endif
u_int32_t htonl(u_int32_t hostlong)
{
return swap32(hostlong);
}
u_int32_t ntohl(u_int32_t netlong)
{
return swap32(netlong);
}
u_int16_t htons(u_int16_t hostshort)
{
return swap16(hostshort);
}
u_int16_t ntohs(u_int16_t netshort)
{
return swap16(netshort);
}
+63
View File
@@ -0,0 +1,63 @@
# Copyright (C) 2007-2010 Apple Inc. All rights reserved.
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LIBC_DIR := $(GET_LOCAL_DIR)
LIBC_BUILD := $(call TOLIBDIR,$(LIBC_DIR)/LIBC.a)
COMMONLIBS += LIBC
# Only process the remainder of the makefile if we are building libraries
#
ifeq ($(MAKEPHASE),libraries)
# base library files
LIBC_OBJS := \
$(LIBC_DIR)/atoi.o \
$(LIBC_DIR)/ctype.o \
$(LIBC_DIR)/endian.o \
$(LIBC_DIR)/log2.o \
$(LIBC_DIR)/memcpy_chk.o \
$(LIBC_DIR)/memmove_chk.o \
$(LIBC_DIR)/memset_chk.o \
$(LIBC_DIR)/misc.o \
$(LIBC_DIR)/printf.o \
$(LIBC_DIR)/printf_chk.o \
$(LIBC_DIR)/qsort.o \
$(LIBC_DIR)/stdio.o \
$(LIBC_DIR)/stdlib.o \
$(LIBC_DIR)/strlcat_chk.o \
$(LIBC_DIR)/strlcpy_chk.o \
$(LIBC_DIR)/strtol.o \
$(LIBC_DIR)/strtoll.o \
$(LIBC_DIR)/strtoul.o \
$(LIBC_DIR)/strtoull.o
# handle architecture-specific overrides for string functions
ARCH_STROPS :=
-include $(LIBC_DIR)/$(ARCH)/rules.mk
STROPS := bcopy bzero memchr memcmp memcpy memmove memscan memset strchr\
strcmp strcoll strdup strlcat strlcpy strlen strncmp \
strnicmp strnlen strpbrk strrchr strsep strspn strstr strtok strxfrm
# filter out the strops that the arch code doesn't already specify
STROPS := $(filter-out $(ARCH_STROPS),$(STROPS))
STROPS_FILES := $(addsuffix .o,$(addprefix $(LIBC_DIR)/,$(STROPS)))
LIBC_OBJS += \
$(STROPS_FILES)
LIBC_OBJS := $(call TOLIBOBJDIR,$(LIBC_OBJS))
$(LIBC_BUILD): $(LIBC_OBJS)
ALL_DEPS += $(LIBC_OBJS:%o=%d)
endif
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <lib/libiboot.h>
int log2_int(unsigned int val)
{
if (val == 0)
return 0;
return 31 - __builtin_clz(val);
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
void *
memchr(void const *buf, int c, size_t len)
{
size_t i;
unsigned char const *b= buf;
unsigned char x= (c&0xff);
for(i= 0; i< len; i++) {
if(b[i]== x) {
return (void*)(b+i);
}
}
return NULL;
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2007-2008 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <string.h>
#include <sys/types.h>
int
memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
signed char res = 0;
for(su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if((res = *su1 - *su2) != 0)
break;
return res;
}
/*
* memcmp_secure
*
* memcmp with constant execution time for a given compare length.
*/
int
memcmp_secure(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
unsigned char res = 0;
for(su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
res |= *su1 ^ *su2;
return res ? 1 : 0;
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <compiler.h>
#include <string.h>
#include <sys/types.h>
#include <sys.h>
#if defined(memcpy)
#undef memcpy
#endif
void *
__memcpy_chk(void *dst, void const *src, size_t s, size_t chk_size)
{
if (unlikely(chk_size < s))
panic("object size check failed (%zu < %zu)", s, chk_size);
return memcpy(dst, src, s);
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <compiler.h>
#include <string.h>
#include <sys/types.h>
#include <sys.h>
#if defined(memmove)
#undef memmove
#endif
void *
__memmove_chk(void *dst, void const *src, size_t s, size_t chk_size)
{
if (unlikely(chk_size < s))
panic("object size check failed (%zu < %zu)", s, chk_size);
return memmove(dst, src, s);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <ctype.h>
void *memscan(void *addr, int c, size_t size)
{
unsigned char *p = (unsigned char *)addr;
while(size) {
if(*p == c)
return (void *)p;
p++;
size--;
}
return (void *)p;
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <compiler.h>
#include <string.h>
#include <sys/types.h>
#include <sys.h>
#if defined(memset)
#undef memset
#endif
void *
__memset_chk(void *dst, int c, size_t s, size_t chk_size)
{
if (unlikely(chk_size < s))
panic("object size check failed (%zu < %zu)", s, chk_size);
return memset(dst, c, s);
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <compiler.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
void hexdump(const void *_ptr, size_t len)
{
const unsigned char *ptr = _ptr;
unsigned int i;
printf("hexdump ptr %p, len %zd\n", ptr, len);
while (len > 0) {
printf("%p: ", ptr);
for (i=0; i < __min(len, 16u); i++) {
printf("%02x ", *ptr);
ptr++;
}
printf("\n");
if (len < 16)
break;
len -= 16;
}
}
+482
View File
@@ -0,0 +1,482 @@
/*
* Copyright (C) 2007-2012 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <lib/libc.h>
#if defined(snprintf)
#undef snprintf
#endif
#if defined(vsnprintf)
#undef vsnprintf
#endif
typedef void (* printf_outfunc_t)(void *arg, char c);
typedef struct {
printf_outfunc_t func;
size_t size;
char *buf;
size_t offset;
} printf_outfunc_state_t;
/* Make external libraries which uses AssertMacros header to link successfully */
void * __stderrp = NULL;
static int do_printf(printf_outfunc_state_t *state, const char *fmt, va_list ap);
static void printf_outfunc_state_init(printf_outfunc_state_t *state, printf_outfunc_t func, size_t size, char *buf)
{
state->func = func;
state->size = size;
state->buf = buf;
state->offset = 0;
/* Terminate the start of the buffer but not the end.
* See <rdar://problem/8964339> 3.1.10 snprintf unsafe buffer write.
* This guards against an attacker theoretically tampering with 'size' and
* having the ability to place a zero at any memory location. */
if ((state->buf != NULL) && (state->size > 0))
state->buf[0] = '\0';
}
static void stdout_outfunc(void *arg __unused, char c)
{
/* Don't emit the trailing NUL, as it's only applicable to sprintf and
* friends
*/
if (c != '\0')
LIBC_FUNC(putchar)(c);
}
static void string_outfunc(void *arg, char c)
{
printf_outfunc_state_t *state = (printf_outfunc_state_t *)arg;
if ((state->buf != NULL) && (state->offset < (state->size - 1))) {
state->buf[state->offset++] = c;
/* String will never be unterminated. */
if (c != '\0') {
state->buf[state->offset] = '\0';
}
}
}
int LIBC_FUNC(fprintf)(void *stream __unused, const char *fmt, ...)
{
int err;
va_list ap;
va_start(ap, fmt);
err = LIBC_FUNC(vprintf)(fmt, ap);
va_end(ap);
return err;
}
int LIBC_FUNC(printf)(const char *fmt, ...)
{
int err;
va_list ap;
va_start(ap, fmt);
err = LIBC_FUNC(vprintf)(fmt, ap);
va_end(ap);
return err;
}
int LIBC_FUNC(vprintf)(const char *fmt, va_list ap)
{
printf_outfunc_state_t state;
printf_outfunc_state_init(&state, stdout_outfunc, 0, NULL);
return do_printf(&state, fmt, ap);
}
int LIBC_FUNC(snprintf)(char *str, size_t size, const char *fmt, ...)
{
int err;
va_list ap;
va_start(ap, fmt);
err = LIBC_FUNC(vsnprintf)(str, size, fmt, ap);
va_end(ap);
return err;
}
int LIBC_FUNC(vsnprintf)(char *str, size_t size, const char *fmt, va_list ap)
{
printf_outfunc_state_t state;
int result;
char dummy[2];
if (size == 0) {
/* string_outfunc doesn't handle zero sized buffers gracefully,
* write into a small safe buffer instead */
str = dummy;
size = 2;
}
printf_outfunc_state_init(&state, string_outfunc, size, str);
result = do_printf(&state, fmt, ap);
/* String is always terminated by each call to string_outfunc. */
return(result);
}
static char *longlong_to_string(char *buf, unsigned long long n, int len, int sign, int showsign, int zeropad)
{
int pos = len;
int negative = 0;
if(sign && (long long)n < 0) {
negative = 1;
n = -n;
}
buf[--pos] = 0;
/* only do the math if the number is >= 10 */
while(n >= 10) {
int digit = n % 10;
n /= 10;
buf[--pos] = digit + '0';
}
buf[--pos] = n + '0';
/* see if we need to zero pad this */
while ((len - pos - 1) < zeropad) {
buf[--pos] = '0';
}
if(negative)
buf[--pos] = '-';
else if(showsign)
buf[--pos] = '+';
return &buf[pos];
}
static char *longlong_to_hexstring(char *buf, unsigned long long u, int len, int caps)
{
int pos = len;
static const char hextable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static const char hextable_caps[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
const char *table;
if(caps)
table = hextable_caps;
else
table = hextable;
buf[--pos] = 0;
do {
unsigned int digit = u % 16;
u /= 16;
buf[--pos] = table[digit];
} while(u != 0);
return &buf[pos];
}
#define LONGFLAG 0x00000001
#define LONGLONGFLAG 0x00000002
#define HALFFLAG 0x00000004
#define HALFHALFFLAG 0x00000008
#define SIZETFLAG 0x00000010
#define ALTFLAG 0x00000020
#define CAPSFLAG 0x00000040
#define SIGNFLAG 0x00000080
#define LEADZERO 0x00000100
#define SEENDOT 0x00000200
#define PADRIGHT 0x00000400
#define NUMERIC 0x00000800
static int do_printf(printf_outfunc_state_t *state, const char *fmt, va_list ap)
{
char c;
unsigned char uc;
const char *s;
const char *prefix_string;
unsigned long long n;
int flags;
size_t chars_written = 0;
char num_buffer[32];
int nummod[2];
int curr_mod;
#define OUTPUT_CHAR(c) do { state->func(state, c); chars_written++; } while(0)
for(;;) {
/* handle regular chars that aren't format related */
while((c = *fmt++) != 0) {
if(c == '%')
break; /* we saw a '%', break and start parsing format */
OUTPUT_CHAR(c);
}
/* make sure we haven't just hit the end of the string */
if(c == 0)
break;
/* reset the format state */
curr_mod = nummod[0] = nummod[1] = flags = 0;
prefix_string = NULL;
next_format:
/* grab the next format character */
c = *fmt++;
if(c == 0)
break;
switch(c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (c == '0' && nummod[0] == 0) {
flags |= LEADZERO;
goto next_format;
}
nummod[curr_mod] *= 10;
nummod[curr_mod] += (c - '0');
goto next_format;
case '*':
nummod[curr_mod] = va_arg(ap, int);
goto next_format;
case '.':
if (curr_mod == 0)
curr_mod = 1;
goto next_format;
case '-':
flags |= PADRIGHT;
flags &= ~LEADZERO;
goto next_format;
case '%':
OUTPUT_CHAR('%');
break;
case 'c':
uc = va_arg(ap, unsigned int);
OUTPUT_CHAR(uc);
break;
case 's':
s = va_arg(ap, const char *);
if(s == 0)
s = "<null>";
goto _output_string;
case '+':
flags |= SIGNFLAG;
goto next_format;
case '#':
flags |= ALTFLAG;
goto next_format;
case 'l':
if(flags & LONGFLAG)
flags |= LONGLONGFLAG;
flags |= LONGFLAG;
goto next_format;
case 'h':
if(flags & HALFFLAG)
flags |= HALFHALFFLAG;
flags |= HALFFLAG;
goto next_format;
case 'z':
flags |= SIZETFLAG;
goto next_format;
case 'i':
case 'd':
flags |= NUMERIC;
n = (flags & LONGLONGFLAG) ? va_arg(ap, long long) :
(flags & LONGFLAG) ? va_arg(ap, long) :
(flags & HALFHALFFLAG) ? (signed char)va_arg(ap, int) :
(flags & HALFFLAG) ? (short)va_arg(ap, int) :
(flags & SIZETFLAG) ? va_arg(ap, ssize_t) :
va_arg(ap, int);
s = longlong_to_string(num_buffer, n, sizeof(num_buffer), 1, flags & SIGNFLAG, 0);
goto _output_string;
case 'u':
flags |= NUMERIC;
n = (flags & LONGLONGFLAG) ? va_arg(ap, unsigned long long) :
(flags & LONGFLAG) ? va_arg(ap, unsigned long) :
(flags & HALFHALFFLAG) ? (unsigned char)va_arg(ap, unsigned int) :
(flags & HALFFLAG) ? (unsigned short)va_arg(ap, unsigned int) :
(flags & SIZETFLAG) ? va_arg(ap, size_t) :
va_arg(ap, unsigned int);
s = longlong_to_string(num_buffer, n, sizeof(num_buffer), 0, flags & SIGNFLAG, 0);
goto _output_string;
case 'p':
#if !RELEASE_BUILD
flags |= LONGFLAG | ALTFLAG;
goto hex;
#else
// need to consume the argument
n = (unsigned)va_arg(ap, void *);
// but we don't want to print the pointer
s = "<ptr>";
goto _output_string;
#endif
case 'X':
flags |= CAPSFLAG;
goto hex;
hex:
case 'x':
flags |= NUMERIC;
n = (flags & LONGLONGFLAG) ? va_arg(ap, unsigned long long) :
(flags & LONGFLAG) ? va_arg(ap, unsigned long) :
(flags & HALFHALFFLAG) ? (unsigned char)va_arg(ap, unsigned int) :
(flags & HALFFLAG) ? (unsigned short)va_arg(ap, unsigned int) :
(flags & SIZETFLAG) ? va_arg(ap, size_t) :
va_arg(ap, unsigned int);
s = longlong_to_hexstring(num_buffer, n, sizeof(num_buffer), flags & CAPSFLAG);
if(flags & ALTFLAG)
prefix_string = "0x";
goto _output_string;
case 'I':
{
unsigned char *ip, lip[4];
char ipbuf[4];
int i;
/* IP address */
ip = (unsigned char *)va_arg(ap, void *);
num_buffer[0] = 0;
if (flags & ALTFLAG) {
lip[0] = ip[3];
lip[1] = ip[2];
lip[2] = ip[1];
lip[3] = ip[0];
} else {
lip[0] = ip[0];
lip[1] = ip[1];
lip[2] = ip[2];
lip[3] = ip[3];
}
ipbuf[0] = 0;
for (i = 0; i < 4; i++) {
s = longlong_to_string(ipbuf, lip[i], sizeof(ipbuf), 0, 0, 0);
strlcat(num_buffer, s, sizeof(num_buffer));
if (i < 3)
strlcat(num_buffer, ".", sizeof(num_buffer));
}
s = num_buffer;
goto _output_string;
}
case 'M':
{
unsigned char *mac;
/* ethernet MAC address */
mac = (unsigned char *)va_arg(ap, void *);
char macbuf[4];
int i;
num_buffer[0] = 0;
for (i = 0; i < 6; i++) {
s = longlong_to_hexstring(macbuf, mac[i], sizeof(macbuf), 0);
strlcat(num_buffer, s, sizeof(num_buffer));
if (i < 5)
strlcat(num_buffer, ":", sizeof(num_buffer));
}
s = num_buffer;
goto _output_string;
}
case 'n':
/*
* XXX Do not implement %n, as it is the main
* basis for printf format-string attacks.
*/
break;
default:
OUTPUT_CHAR('%');
OUTPUT_CHAR(c);
break;
}
/* move on to the next field */
continue;
/* shared output code */
_output_string:
if (nummod[0] > 0) {
int output_len = (int)strlen(s);
int prefix_len = prefix_string == NULL ? 0 : (int)strlen(prefix_string);
if (nummod[0] < (output_len + prefix_len))
nummod[0] = 0;
}
if (nummod[0] > 0) {
if (!(flags & PADRIGHT)) {
/* lead pad the string with either zero or space */
char pad = (flags & LEADZERO) ? '0' : ' ';
int len = strlen(s);
if (prefix_string)
len += strlen(prefix_string);
if (nummod[0] > len) {
len = nummod[0] - len;
nummod[0] -= len;
// sign bit goes before 0-padding
if ((flags & NUMERIC) && pad == '0' &&
(s[0] == '-' || s[0] == '+')) {
OUTPUT_CHAR(*s++);
nummod[0]--;
}
if (prefix_string && pad == '0') {
while(*prefix_string != 0)
OUTPUT_CHAR(*prefix_string++);
prefix_string = NULL;
}
while (len-- > 0)
OUTPUT_CHAR(pad);
}
}
} else if (nummod[0] == 0) {
nummod[0] = INT_MAX;
flags &= ~PADRIGHT; /* otherwise we will print a lot of spaces */
}
if (prefix_string) {
while(*prefix_string != 0 && (nummod[0]-- > 0))
OUTPUT_CHAR(*prefix_string++);
}
while(*s != 0 && (nummod[0]-- > 0))
OUTPUT_CHAR(*s++);
if (flags & PADRIGHT) {
while (nummod[0]-- > 0)
OUTPUT_CHAR(' ');
}
continue;
}
return chars_written;
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <compiler.h>
#include <debug.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
#if defined(snprintf)
#undef snprintf
#endif
#if defined(vsnprintf)
#undef vsnprintf
#endif
int
__snprintf_chk(char *dst, size_t size, int flags __unused, size_t chk_size, const char *fmt, ...)
{
int result;
va_list ap;
if (unlikely(chk_size < size))
panic("object size check failed (%zu < %zu)", size, chk_size);
va_start(ap, fmt);
result = vsnprintf(dst, size, fmt, ap);
va_end(ap);
return result;
}
int
__vsnprintf_chk(char *dst, size_t size, int flags __unused, size_t chk_size, const char *fmt, va_list ap)
{
if (unlikely(chk_size < size))
panic("object size check failed (%zu < %zu)", size, chk_size);
return vsnprintf(dst, size, fmt, ap);
}
+194
View File
@@ -0,0 +1,194 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <stdlib.h>
#ifdef I_AM_QSORT_R
typedef int cmp_t(void *, const void *, const void *);
#else
typedef int cmp_t(const void *, const void *);
#endif
static inline char *med3(char *, char *, char *, cmp_t *, void *);
static inline void swapfunc(char *, char *, int, int);
#ifndef min
#define min(a, b) (a) < (b) ? a : b
#endif
/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*/
#define swapcode(TYPE, parmi, parmj, n) { \
long i = (n) / sizeof (TYPE); \
TYPE *pi = (TYPE *) (parmi); \
TYPE *pj = (TYPE *) (parmj); \
do { \
TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
}
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
static inline void
swapfunc(a, b, n, swaptype)
char *a, *b;
int n, swaptype;
{
if(swaptype <= 1)
swapcode(long, a, b, n)
else
swapcode(char, a, b, n)
}
#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
#ifdef I_AM_QSORT_R
#define CMP(t, x, y) (cmp((t), (x), (y)))
#else
#define CMP(t, x, y) (cmp((x), (y)))
#endif
static inline char *
med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
#ifndef I_AM_QSORT_R
__unused
#endif
)
{
return CMP(thunk, a, b) < 0 ?
(CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
:(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
}
#ifdef I_AM_QSORT_R
void
qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
#else
#define thunk NULL
void
qsort(void *a, size_t n, size_t es, cmp_t *cmp)
#endif
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
int d, r, swaptype, swap_cnt;
loop: SWAPINIT(a, es);
swap_cnt = 0;
if (n < 7) {
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
for (pl = pm;
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pm = (char *)a + (n / 2) * es;
if (n > 7) {
pl = a;
pn = (char *)a + (n - 1) * es;
if (n > 40) {
d = (n / 8) * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
pm = med3(pm - d, pm, pm + d, cmp, thunk);
pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
}
pm = med3(pl, pm, pn, cmp, thunk);
}
swap(a, pm);
pa = pb = (char *)a + es;
pc = pd = (char *)a + (n - 1) * es;
for (;;) {
while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pc, pd);
pd -= es;
}
pc -= es;
}
if (pb > pc)
break;
swap(pb, pc);
swap_cnt = 1;
pb += es;
pc -= es;
}
if (swap_cnt == 0) { /* Switch to insertion sort */
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
for (pl = pm;
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pn = (char *)a + n * es;
r = min(pa - (char *)a, pb - pa);
vecswap(a, pb - r, r);
r = min((int)(pd - pc), (int)(pn - pd - es));
vecswap(pb, pn - r, r);
if ((r = pb - pa) > (int)es)
#ifdef I_AM_QSORT_R
qsort_r(a, r / es, es, thunk, cmp);
#else
qsort(a, r / es, es, cmp);
#endif
if ((r = pd - pc) > (int)es) {
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
goto loop;
}
/* qsort(pn - r, r / es, es, cmp);*/
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <lib/libc.h>
#include <sys.h>
int errno = 0;
int puts(const char *str)
{
enter_critical_section();
while(*str) {
putchar(*str);
str++;
}
exit_critical_section();
return 0;
}
int getchar(void)
{
char c;
c = debug_getchar();
if (c == '\r')
c = '\n';
return c;
}
int putchar(int c)
{
if (c == '\n')
debug_putchar('\r');
debug_putchar(c);
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <lib/libc.h>
#include <sys.h>
static int randseed = 12345;
int system(const char *string)
{
printf("unsupported: system(%s)\n", string);
return -1;
}
void exit(int status)
{
panic("exit(%d) called\n", status);
for (;;)
;
}
int rand(void)
{
return (randseed = randseed * 12345 + 17);
}
void srand(unsigned int seed)
{
randseed = (int)seed;
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
char *
strchr(const char *s, int c)
{
for(; *s != (char) c; ++s)
if (*s == '\0')
return NULL;
return (char *) s;
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
int
strcmp(char const *cs, char const *ct)
{
signed char __res;
while(1) {
if((__res = *cs - *ct++) != 0 || !*cs++)
break;
}
return __res;
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
int
strcoll(const char *s1, const char *s2)
{
return strcmp(s1, s2);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <stdlib.h>
#include <string.h>
char *
strdup(const char *str)
{
size_t len;
char *copy;
len = strlen(str) + 1;
copy = malloc(len);
memcpy(copy, str, len);
return copy;
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2007-2009 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <sys/types.h>
#include <string.h>
#include <sys.h>
#if defined(strlcat)
#undef strlcat
#endif
size_t
strlcat(char *dst, char const *src, size_t s)
{
size_t i;
size_t j= strnlen(dst, s);
if(!s || (s== j)) {
return j+strlen(src);
}
dst+= j;
s-= j;
for(i= 0; ((i< s-1) && src[i]); i++) {
dst[i]= src[i];
}
dst[i]= 0;
return j + i + strlen(src+i);
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <sys/types.h>
#include <string.h>
#include <sys.h>
#if defined(strlcat)
#undef strlcat
#endif
size_t
__strlcat_chk(char *dst, char const *src, size_t s, size_t chk_size)
{
if (unlikely(chk_size < s))
panic("object size check failed (%zu < %zu)", s, chk_size);
return strlcat(dst, src, s);
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
#include <sys.h>
#if defined(strlcpy)
#undef strlcpy
#endif
size_t
strlcpy(char *dst, char const *src, size_t s)
{
size_t i= 0;
if(!s) {
return strlen(src);
}
for(i= 0; ((i< s-1) && src[i]); i++) {
dst[i]= src[i];
}
dst[i]= 0;
return i + strlen(src+i);
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <compiler.h>
#include <string.h>
#include <sys/types.h>
#include <sys.h>
#if defined(strlcpy)
#undef strlcpy
#endif
size_t
__strlcpy_chk(char *dst, char const *src, size_t s, size_t chk_size)
{
if (unlikely(chk_size < s))
panic("object size check failed (%zu < %zu)", s, chk_size);
return strlcpy(dst, src, s);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
size_t
strlen(char const *s)
{
size_t i;
i= 0;
while(s[i]) {
i+= 1;
}
return i;
}
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
int
strncmp(char const *cs, char const *ct, size_t count)
{
signed char __res = 0;
while(count > 0) {
if ((__res = *cs - *ct++) != 0 || !*cs++)
break;
count--;
}
return __res;
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
int
strnicmp(char const *s1, char const *s2, size_t len)
{
unsigned char c1 = '\0';
unsigned char c2 = '\0';
if(len > 0) {
do {
c1 = *s1; c2 = *s2;
s1++; s2++;
if(!c1)
break;
if(!c2)
break;
if(c1 == c2)
continue;
c1 = tolower(c1);
c2 = tolower(c2);
if (c1 != c2)
break;
} while(--len);
}
return (int)c1 - (int)c2;
}
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
size_t
strnlen(char const *s, size_t count)
{
const char *sc;
for(sc = s; count-- && *sc != '\0'; ++sc)
;
return sc - s;
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
char *
strpbrk(char const *cs, char const *ct)
{
const char *sc1;
const char *sc2;
for(sc1 = cs; *sc1 != '\0'; ++sc1) {
for(sc2 = ct; *sc2 != '\0'; ++sc2) {
if(*sc1 == *sc2)
return (char *)sc1;
}
}
return NULL;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
char *
strrchr(char const *s, int c)
{
char const *last= c?0:s;
while(*s) {
if(*s== c) {
last= s;
}
s+= 1;
}
return (char *)last;
}
+67
View File
@@ -0,0 +1,67 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <string.h>
/*
* Get next token from string *stringp, where tokens are possibly-empty
* strings separated by characters from delim.
*
* Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strsep returns NULL.
*/
char * strsep(char **stringp, const char *delim)
{
char *s;
const char *spanp;
int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
__builtin_unreachable();
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
size_t
strspn(char const *s, char const *accept)
{
const char *p;
const char *a;
size_t count = 0;
for(p = s; *p != '\0'; ++p) {
for(a = accept; *a != '\0'; ++a) {
if(*p == *a)
break;
}
if(*a == '\0')
return count;
++count;
}
return count;
}
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
char *
strstr(char const *s1, char const *s2)
{
int l1, l2;
l2 = strlen(s2);
if (!l2)
return (char *)s1;
l1 = strlen(s1);
while(l1 >= l2) {
l1--;
if (!memcmp(s1,s2,l2))
return (char *)s1;
s1++;
}
return NULL;
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
static char *___strtok = NULL;
char *
strtok(char *s, char const *ct)
{
char *sbegin, *send;
sbegin = s ? s : ___strtok;
if (!sbegin) {
return NULL;
}
sbegin += strspn(sbegin,ct);
if (*sbegin == '\0') {
___strtok = NULL;
return( NULL );
}
send = strpbrk( sbegin, ct);
if (send && *send != '\0')
*send++ = '\0';
___strtok = send;
return (sbegin);
}
+136
View File
@@ -0,0 +1,136 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
/*
* Convert a string to a long integer.
*
* Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
{
const char *s;
unsigned long acc;
char c;
unsigned long cutoff;
int neg, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do {
c = *s++;
} while (isspace((unsigned char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36)
goto noconv;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set 'any' if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
: LONG_MAX;
cutlim = cutoff % base;
cutoff /= base;
for ( ; ; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (!any) {
noconv:
errno = EINVAL;
} else if (neg)
acc = -acc;
if (endptr != NULL)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
+136
View File
@@ -0,0 +1,136 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
/*
* Convert a string to a long long integer.
*
* Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long
strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
{
const char *s;
unsigned long long acc;
char c;
unsigned long long cutoff;
int neg, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do {
c = *s++;
} while (isspace((unsigned char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36)
goto noconv;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for quads is
* [-9223372036854775808..9223372036854775807] and the input base
* is 10, cutoff will be set to 922337203685477580 and cutlim to
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
* accumulated a value > 922337203685477580, or equal but the
* next digit is > 7 (or 8), the number is too big, and we will
* return a range error.
*
* Set 'any' if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
: LLONG_MAX;
cutlim = cutoff % base;
cutoff /= base;
for ( ; ; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LLONG_MIN : LLONG_MAX;
errno = ERANGE;
} else if (!any) {
noconv:
errno = EINVAL;
} else if (neg)
acc = -acc;
if (endptr != NULL)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
+114
View File
@@ -0,0 +1,114 @@
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
/*
* Convert a string to an unsigned long integer.
*
* Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long
strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
{
const char *s;
unsigned long acc;
char c;
unsigned long cutoff;
int neg, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
s = nptr;
do {
c = *s++;
} while (isspace((unsigned char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36)
goto noconv;
cutoff = ULONG_MAX / base;
cutlim = ULONG_MAX % base;
for ( ; ; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
errno = ERANGE;
} else if (!any) {
noconv:
errno = EINVAL;
} else if (neg)
acc = -acc;
if (endptr != NULL)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
+114
View File
@@ -0,0 +1,114 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
/*
* Convert a string to an unsigned long long integer.
*
* Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long long
strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
{
const char *s;
unsigned long long acc;
char c;
unsigned long long cutoff;
int neg, any, cutlim;
/*
* See strtoq for comments as to the logic used.
*/
s = nptr;
do {
c = *s++;
} while (isspace((unsigned char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36)
goto noconv;
cutoff = ULLONG_MAX / base;
cutlim = ULLONG_MAX % base;
for ( ; ; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULLONG_MAX;
errno = ERANGE;
} else if (!any) {
noconv:
errno = EINVAL;
} else if (neg)
acc = -acc;
if (endptr != NULL)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
#include <string.h>
#include <sys/types.h>
size_t
strxfrm(char *dest, const char *src, size_t n)
{
size_t len = strlen(src);
if(n) {
size_t copy_len = len < n ? len : n - 1;
memcpy(dest, src, copy_len);
dest[copy_len] = 0;
}
return len;
}
+401
View File
@@ -0,0 +1,401 @@
#include <unittest.h>
#include <lib/libc.h>
#include <string.h>
int libc_putchar(int c)
{
return c;
}
void test_snprintf(uintptr_t param)
{
char buf[200];
int result;
////////////////////////////////////////////////////////////
// Tests for format strings without conversion specifiers //
////////////////////////////////////////////////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "");
TEST_ASSERT_STR_EQ(buf, "");
TEST_ASSERT_EQ(result, 0);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "abc");
TEST_ASSERT_STR_EQ(buf, "abc");
TEST_ASSERT_EQ(result, 3);
// short length truncates output, but returns untruncated length
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, 1, "abc");
TEST_ASSERT_STR_EQ(buf, "");
TEST_ASSERT_EQ(result, 3);
// short length truncates output, but returns untruncated length
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, 2, "abc");
TEST_ASSERT_STR_EQ(buf, "a");
TEST_ASSERT_EQ(result, 3);
// length of 0 results in untouched buffer
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, 0, "abc");
TEST_ASSERT_EQ((uint8_t)buf[0], 1);
TEST_ASSERT_EQ((uint8_t)buf[1], 1);
TEST_ASSERT_EQ((uint8_t)buf[2], 1);
TEST_ASSERT_EQ((uint8_t)buf[3], 1);
TEST_ASSERT_EQ(result, 3);
//////////////////
// Tests for %% //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%%");
TEST_ASSERT_STR_EQ(buf, "%");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, 1, "%%");
TEST_ASSERT_STR_EQ(buf, "");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%%");
TEST_ASSERT_STR_EQ(buf, "%");
TEST_ASSERT_EQ(result, 1);
//////////////////
// Tests for %s //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%s", "abc");
TEST_ASSERT_STR_EQ(buf, "abc");
TEST_ASSERT_EQ(result, 3);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "123%sXYZ", "abc");
TEST_ASSERT_STR_EQ(buf, "123abcXYZ");
TEST_ASSERT_EQ(result, 9);
// truncating in middle of conversion
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, 5, "%s", "abcdefgh");
TEST_ASSERT_STR_EQ(buf, "abcd");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%10s", "abc");
TEST_ASSERT_STR_EQ(buf, " abc");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%-10s", "abc");
TEST_ASSERT_STR_EQ(buf, "abc ");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%1s", "abc");
TEST_ASSERT_STR_EQ(buf, "abc");
TEST_ASSERT_EQ(result, 3);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%-1s", "abc");
TEST_ASSERT_STR_EQ(buf, "abc");
TEST_ASSERT_EQ(result, 3);
// TODO: truncate in middle of padding
//////////////////
// Tests for %c //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%c", 0x20);
TEST_ASSERT_STR_EQ(buf, " ");
TEST_ASSERT_EQ(result, 1);
//////////////////
// Tests for %d //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", 0);
TEST_ASSERT_STR_EQ(buf, "0");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", 1);
TEST_ASSERT_STR_EQ(buf, "1");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", 1234567890);
TEST_ASSERT_STR_EQ(buf, "1234567890");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", -1);
TEST_ASSERT_STR_EQ(buf, "-1");
TEST_ASSERT_EQ(result, 2);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", -1234567890);
TEST_ASSERT_STR_EQ(buf, "-1234567890");
TEST_ASSERT_EQ(result, 11);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", -1234567890);
TEST_ASSERT_STR_EQ(buf, "-1234567890");
TEST_ASSERT_EQ(result, 11);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", 2147483647);
TEST_ASSERT_STR_EQ(buf, "2147483647");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%d", (int)-2147483648);
TEST_ASSERT_STR_EQ(buf, "-2147483648");
TEST_ASSERT_EQ(result, 11);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04d", 1);
TEST_ASSERT_STR_EQ(buf, "0001");
TEST_ASSERT_EQ(result, 4);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04d", 12345);
TEST_ASSERT_STR_EQ(buf, "12345");
TEST_ASSERT_EQ(result, 5);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04d", -123);
TEST_ASSERT_STR_EQ(buf, "-123");
TEST_ASSERT_EQ(result, 4);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04d", -1234);
TEST_ASSERT_STR_EQ(buf, "-1234");
TEST_ASSERT_EQ(result, 5);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04d", -12345);
TEST_ASSERT_STR_EQ(buf, "-12345");
TEST_ASSERT_EQ(result, 6);
// TODO left and right padding and 0 and ' ' padding in all combos,
// with too much, just enough, and too little
// TODO '+' flag
//////////////////
// Tests for %u //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%u", 0);
TEST_ASSERT_STR_EQ(buf, "0");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%u", 1);
TEST_ASSERT_STR_EQ(buf, "1");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%u", 1234567890);
TEST_ASSERT_STR_EQ(buf, "1234567890");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%u", 2147483647);
TEST_ASSERT_STR_EQ(buf, "2147483647");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%u", 4294967295u);
TEST_ASSERT_STR_EQ(buf, "4294967295");
TEST_ASSERT_EQ(result, 10);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04u", 1);
TEST_ASSERT_STR_EQ(buf, "0001");
TEST_ASSERT_EQ(result, 4);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%04u", 12345);
TEST_ASSERT_STR_EQ(buf, "12345");
TEST_ASSERT_EQ(result, 5);
//////////////////
// Tests for %x //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%x", 0);
TEST_ASSERT_STR_EQ(buf, "0");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%#x", 0);
TEST_ASSERT_STR_EQ(buf, "0x0");
TEST_ASSERT_EQ(result, 3);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%x", 1);
TEST_ASSERT_STR_EQ(buf, "1");
TEST_ASSERT_EQ(result, 1);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%#x", 1);
TEST_ASSERT_STR_EQ(buf, "0x1");
TEST_ASSERT_EQ(result, 3);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%x", 0x1234abcd);
TEST_ASSERT_STR_EQ(buf, "1234abcd");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%x", 0x567890ef);
TEST_ASSERT_STR_EQ(buf, "567890ef");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%x", 0xffffffff);
TEST_ASSERT_STR_EQ(buf, "ffffffff");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%8x", 0x1234);
TEST_ASSERT_STR_EQ(buf, " 1234");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%#8x", 0x1234);
TEST_ASSERT_STR_EQ(buf, " 0x1234");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%08x", 0x1234);
TEST_ASSERT_STR_EQ(buf, "00001234");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%#08x", 0x1234);
TEST_ASSERT_STR_EQ(buf, "0x001234");
TEST_ASSERT_EQ(result, 8);
//////////////////
// Tests for %X //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%X", 0x1234abcd);
TEST_ASSERT_STR_EQ(buf, "1234ABCD");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%X", 0x567890ef);
TEST_ASSERT_STR_EQ(buf, "567890EF");
TEST_ASSERT_EQ(result, 8);
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%8x", 0x1234);
TEST_ASSERT_STR_EQ(buf, " 1234");
TEST_ASSERT_EQ(result, 8);
//////////////////
// Tests for %p //
//////////////////
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%p", (void *)0);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, "0x0");
TEST_ASSERT_EQ(result, 3);
#else
TEST_ASSERT_STR_EQ(buf, "<ptr>");
TEST_ASSERT_EQ(result, 5);
#endif
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%p", (void *)0x12345678);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, "0x12345678");
TEST_ASSERT_EQ(result, 10);
#else
TEST_ASSERT_STR_EQ(buf, "<ptr>");
TEST_ASSERT_EQ(result, 5);
#endif
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%p %d", (void *)0x12345678, 5555);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, "0x12345678 5555");
TEST_ASSERT_EQ(result, 15);
#else
TEST_ASSERT_STR_EQ(buf, "<ptr> 5555");
TEST_ASSERT_EQ(result, 10);
#endif
// make sure we don't truncate %p conversions when the output is longer
// than the minimum field width
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%3p", (void *)0x12345);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, "0x12345");
TEST_ASSERT_EQ(result, 7);
#else
TEST_ASSERT_STR_EQ(buf, "<ptr>");
TEST_ASSERT_EQ(result, 5);
#endif
// make sure we don't truncate %p conversions when the output minus the
// 0x is equal to the minimum field width
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%5p", (void *)0x12345);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, "0x12345");
TEST_ASSERT_EQ(result, 7);
#else
TEST_ASSERT_STR_EQ(buf, "<ptr>");
TEST_ASSERT_EQ(result, 5);
#endif
// minimum field width is inclusive of the 0x
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%7p", (void *)0x12345);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, "0x12345");
TEST_ASSERT_EQ(result, 7);
#else
TEST_ASSERT_STR_EQ(buf, " <ptr>");
TEST_ASSERT_EQ(result, 7);
#endif
// verify padding occurs on %p when output is smaller than
// minimum field width
memset(buf, 1, sizeof(buf));
result = libc_snprintf(buf, sizeof(buf), "%9p", (void *)0x12345);
#if !RELEASE_BUILD
TEST_ASSERT_STR_EQ(buf, " 0x12345");
TEST_ASSERT_EQ(result, 9);
#else
TEST_ASSERT_STR_EQ(buf, " <ptr>");
TEST_ASSERT_EQ(result, 9);
#endif
}
struct test_suite printf_suite = {
.name = "printf",
.test_cases = {
{ "snprintf", test_snprintf, 0, "Tests the snprintf function" },
TEST_CASE_LAST
}
};
TEST_SUITE(printf_suite);
+17
View File
@@ -0,0 +1,17 @@
# Copyright (C) 2014 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
TEST_OBJS := \
$(LOCAL_DIR)/printf.o
TEST_SUPPORT_OBJS := \
tests/unittest-main.o \
$(LOCAL_DIR)/test_printf.o
+18
View File
@@ -0,0 +1,18 @@
# Copyright (C) 2014 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
TEST_NAME := libc-release
include $(LOCAL_DIR)/tests-base.mk
TEST_CFLAGS += \
-DRELEASE_BUILD=1
+15
View File
@@ -0,0 +1,15 @@
# Copyright (C) 2014 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
include $(LOCAL_DIR)/tests-base.mk
TEST_NAME := libc