first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);*/
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user