text:
.global expm1l
.type expm1l,@function
expm1l:
	fldt 8(%esp)
	fldl2e
	fmulp
	movl $0xc2820000,-4(%esp)
	flds -4(%esp)
	fucomp %st(1)
	fnstsw %ax
	sahf
	fld1
	jb 1f
		# x*log2e <= -65, return -1 without underflow
	fstp %st(1)
	fchs
	ret
1:	fld %st(1)
	fabs
	fucom %st(1)
	fnstsw %ax
	fstp %st(0)
	fstp %st(0)
	sahf
	ja 1f
	f2xm1
	ret
1:	push %rax
	call 1f
	pop %rax
	fld1
	fsubrp
	ret

.global exp2l
.type exp2l,@function
exp2l:
	fldt 8(%esp)
1:	fld %st(0)
	sub $16,%esp
	fstpt (%esp)
	mov 8(%esp),%ax
	and $0x7fff,%ax
	cmp $0x3fff+13,%ax
	jb 4f             # |x| < 8192
	cmp $0x3fff+15,%ax
	jae 3f            # |x| >= 32768
	fsts (%esp)
	cmpl $0xc67ff800,(%esp)
	jb 2f             # x > -16382
	movl $0x5f000000,(%esp)
	flds (%esp)       # 0x1p63
	fld %st(1)
	fsub %st(1)
	faddp
	fucomp %st(1)
	fnstsw
	sahf
	je 2f             # x - 0x1p63 + 0x1p63 == x
	movl $1,(%esp)
	flds (%esp)       # 0x1p-149
	fdiv %st(1)
	fstps (%esp)      # raise underflow
2:	fld1
	fld %st(1)
	frndint
	fxch %st(2)
	fsub %st(2)       # st(0)=x-rint(x), st(1)=1, st(2)=rint(x)
	f2xm1
	faddp             # 2^(x-rint(x))
1:	fscale
	fstp %st(1)
	add $16,%esp
	ret
3:	xor %eax,%eax
4:	cmp $0x3fff-64,%ax
	fld1
	jb 1b             # |x| < 0x1p-64
	fstpt (%esp)
	fistl 8(%esp)
	fildl 8(%esp)
	fsubrp %st(1)
	addl $0x3fff,8(%esp)
	f2xm1
	fld1
	faddp             # 2^(x-rint(x))
	fldt (%esp)       # 2^rint(x)
	fmulp
	add $16,%esp
	ret


text:
.global floorl
.type floorl,@function
floorl:
	fldt 8(%esp)
1:	mov $0x7,%al
1:	fstcw 8(%esp)
	mov 9(%esp),%ah
	mov %al,9(%esp)
	fldcw 8(%esp)
	frndint
	mov %ah,9(%esp)
	fldcw 8(%esp)
	ret

.global ceill
.type ceill,@function
ceill:
	fldt 8(%esp)
	mov $0xb,%al
	jmp 1b

.global truncl
.type truncl,@function
truncl:
	fldt 8(%esp)
	mov $0xf,%al
	jmp 1b

repo_language: C

mime_type: text/x-c


text:
.global fabsf
.type fabsf,@function
fabsf:
	mov $0x7fffffff,%eax
	movq %rax,%xmm1
	andps %xmm1,%xmm0
	ret


text:
.global log10l
.type log10l,@function
log10l:
	fldlg2
	fldt 8(%esp)
	fyl2x
	ret


text:
.global logl
.type logl,@function
logl:
	fldln2
	fldt 8(%esp)
	fyl2x
	ret


text: # see floorl.s


text:
.global lrintf
.type lrintf,@function
lrintf:
	cvtss2si %xmm0,%rax
	ret


text:
.global llrint
.type llrint,@function
llrint:
	cvtsd2si %xmm0,%rax
	ret


text: # see exp2l.s


text:
.global log2l
.type log2l,@function
log2l:
	fld1
	fldt 8(%esp)
	fyl2x
	ret


text:
.global asinl
.type asinl,@function
asinl:
	fldt 8(%esp)
1:	fld %st(0)
	fld1
	fsub %st(0),%st(1)
	fadd %st(2)
	fmulp
	fsqrt
	fpatan
	ret


text:
.global fabs
.type fabs,@function
fabs:
	xor %eax,%eax
	dec %rax
	shr %rax
	movq %rax,%xmm1
	andpd %xmm1,%xmm0
	ret


text:
# exp(x) = 2^hi + 2^hi (2^lo - 1)
# where hi+lo = log2e*x with 128bit precision
# exact log2e*x calculation depends on nearest rounding mode
# using the exact multiplication method of Dekker and Veltkamp

.global expl
.type expl,@function
expl:
	fldt 8(%esp)

		# interesting case: 0x1p-32 <= |x| < 16384
		# check if (exponent|0x8000) is in [0xbfff-32, 0xbfff+13]
	mov 16(%esp), %ax
	or $0x8000, %ax
	sub $0xbfdf, %ax
	cmp $45, %ax
	jbe 2f
	test %ax, %ax
	fld1
	js 1f
		# if |x|>=0x1p14 or nan return 2^trunc(x)
	fscale
	fstp %st(1)
	ret
		# if |x|<0x1p-32 return 1+x
1:	faddp
	ret

		# should be 0x1.71547652b82fe178p0L == 0x3fff b8aa3b29 5c17f0bc
		# it will be wrong on non-nearest rounding mode
2:	fldl2e
	sub $48, %esp
		# hi = log2e_hi*x
		# 2^hi = exp2l(hi)
	fmul %st(1),%st
	fld %st(0)
	fstpt (%esp)
	fstpt 16(%esp)
	fstpt 32(%esp)
	call exp2l
		# if 2^hi == inf return 2^hi
	fld %st(0)
	fstpt (%esp)
	cmpw $0x7fff, 8(%esp)
	je 1f
	fldt 32(%esp)
	fldt 16(%esp)
		# fpu stack: 2^hi x hi
		# exact mult: x*log2e
	fld %st(1)
		# c = 0x1p32+1
	movq $0x41f0000000100000,%rax
	pushq %rax
	fldl (%esp)
		# xh = x - c*x + c*x
		# xl = x - xh
	fmulp
	fld %st(2)
	fsub %st(1), %st
	faddp
	fld %st(2)
	fsub %st(1), %st
		# yh = log2e_hi - c*log2e_hi + c*log2e_hi
	movq $0x3ff7154765200000,%rax
	pushq %rax
	fldl (%esp)
		# fpu stack: 2^hi x hi xh xl yh
		# lo = hi - xh*yh + xl*yh
	fld %st(2)
	fmul %st(1), %st
	fsubp %st, %st(4)
	fmul %st(1), %st
	faddp %st, %st(3)
		# yl = log2e_hi - yh
	movq $0x3de705fc2f000000,%rax
	pushq %rax
	fldl (%esp)
		# fpu stack: 2^hi x lo xh xl yl
		# lo += xh*yl + xl*yl
	fmul %st, %st(2)
	fmulp %st, %st(1)
	fxch %st(2)
	faddp
	faddp
		# log2e_lo
	movq $0xbfbe,%rax
	pushq %rax
	movq $0x82f0025f2dc582ee,%rax
	pushq %rax
	fldt (%esp)
	add $40,%esp
		# fpu stack: 2^hi x lo log2e_lo
		# lo += log2e_lo*x
		# return 2^hi + 2^hi (2^lo - 1)
	fmulp %st, %st(2)
	faddp
	f2xm1
	fmul %st(1), %st
	faddp
1:	add $48, %esp
	ret


text:
.global lrint
.type lrint,@function
lrint:
	cvtsd2si %xmm0,%rax
	ret


text:
.global fmodl
.type fmodl,@function
fmodl:
	fldt 24(%esp)
	fldt 8(%esp)
1:	fprem
	fstsw %ax
	sahf
	jp 1b
	fstp %st(1)
	ret


text:
.global atanl
.type atanl,@function
atanl:
	fldt 8(%esp)
	fld1
	fpatan
	ret


text:
.global sqrt
.type sqrt,@function
sqrt:	sqrtsd %xmm0, %xmm0
	ret


text:
.global llrintf
.type llrintf,@function
llrintf:
	cvtss2si %xmm0,%rax
	ret


text:
.global atan2l
.type atan2l,@function
atan2l:
	fldt 8(%esp)
	fldt 24(%esp)
	fpatan
	ret


text:
.global fabsl
.type fabsl,@function
fabsl:
	fldt 8(%esp)
	fabs
	ret


text:
.global llrintl
.type llrintl,@function
llrintl:
	fldt 8(%esp)
	fistpll 8(%esp)
	mov 8(%esp),%rax
	ret


text:
.global remainderl
.type remainderl,@function
remainderl:
	fldt 24(%esp)
	fldt 8(%esp)
1:	fprem1
	fstsw %ax
	sahf
	jp 1b
	fstp %st(1)
	ret


text:
.global rintl
.type rintl,@function
rintl:
	fldt 8(%rsp)
	frndint
	ret


text:
# see ../i386/acos.s

.global acosl
.type acosl,@function
acosl:
	fldt 8(%rsp)
1:	fld %st(0)
	fld1
	fsub %st(0),%st(1)
	fadd %st(2)
	fmulp
	fsqrt
	fabs
	fxch %st(1)
	fpatan
	ret


text:
.global sqrtf
.type sqrtf,@function
sqrtf:  sqrtss %xmm0, %xmm0
	ret


text:
.global log1pl
.type log1pl,@function
log1pl:
	mov 14(%rsp),%eax
	fldln2
	and $0x7fffffff,%eax
	fldt 8(%rsp)
	cmp $0x3ffd9400,%eax
	ja 1f
	fyl2xp1
	ret
1:	fld1
	faddp
	fyl2x
	ret


text:
.global sqrtl
.type sqrtl,@function
sqrtl:	fldt 8(%rsp)
	fsqrt
	ret


text:
.global lrintl
.type lrintl,@function
lrintl:
	fldt 8(%rsp)
	fistpll 8(%rsp)
	mov 8(%rsp),%rax
	ret


text:
.global expm1l
.type expm1l,@function
expm1l:
	fldt 8(%rsp)
	fldl2e
	fmulp
	movl $0xc2820000,-4(%rsp)
	flds -4(%rsp)
	fucomp %st(1)
	fnstsw %ax
	sahf
	fld1
	jb 1f
		# x*log2e <= -65, return -1 without underflow
	fstp %st(1)
	fchs
	ret
1:	fld %st(1)
	fabs
	fucom %st(1)
	fnstsw %ax
	fstp %st(0)
	fstp %st(0)
	sahf
	ja 1f
	f2xm1
	ret
1:	push %rax
	call 1f
	pop %rax
	fld1
	fsubrp
	ret

.global exp2l
.type exp2l,@function
exp2l:
	fldt 8(%rsp)
1:	fld %st(0)
	sub $16,%rsp
	fstpt (%rsp)
	mov 8(%rsp),%ax
	and $0x7fff,%ax
	cmp $0x3fff+13,%ax
	jb 4f             # |x| < 8192
	cmp $0x3fff+15,%ax
	jae 3f            # |x| >= 32768
	fsts (%rsp)
	cmpl $0xc67ff800,(%rsp)
	jb 2f             # x > -16382
	movl $0x5f000000,(%rsp)
	flds (%rsp)       # 0x1p63
	fld %st(1)
	fsub %st(1)
	faddp
	fucomp %st(1)
	fnstsw
	sahf
	je 2f             # x - 0x1p63 + 0x1p63 == x
	movl $1,(%rsp)
	flds (%rsp)       # 0x1p-149
	fdiv %st(1)
	fstps (%rsp)      # raise underflow
2:	fld1
	fld %st(1)
	frndint
	fxch %st(2)
	fsub %st(2)       # st(0)=x-rint(x), st(1)=1, st(2)=rint(x)
	f2xm1
	faddp             # 2^(x-rint(x))
1:	fscale
	fstp %st(1)
	add $16,%rsp
	ret
3:	xor %eax,%eax
4:	cmp $0x3fff-64,%ax
	fld1
	jb 1b             # |x| < 0x1p-64
	fstpt (%rsp)
	fistl 8(%rsp)
	fildl 8(%rsp)
	fsubrp %st(1)
	addl $0x3fff,8(%rsp)
	f2xm1
	fld1
	faddp             # 2^(x-rint(x))
	fldt (%rsp)       # 2^rint(x)
	fmulp
	add $16,%rsp
	ret


text:
.global floorl
.type floorl,@function
floorl:
	fldt 8(%rsp)
1:	mov $0x7,%al
1:	fstcw 8(%rsp)
	mov 9(%rsp),%ah
	mov %al,9(%rsp)
	fldcw 8(%rsp)
	frndint
	mov %ah,9(%rsp)
	fldcw 8(%rsp)
	ret

.global ceill
.type ceill,@function
ceill:
	fldt 8(%rsp)
	mov $0xb,%al
	jmp 1b

.global truncl
.type truncl,@function
truncl:
	fldt 8(%rsp)
	mov $0xf,%al
	jmp 1b


text:
.global fabsf
.type fabsf,@function
fabsf:
	mov $0x7fffffff,%eax
	movq %rax,%xmm1
	andps %xmm1,%xmm0
	ret


text:
.global log10l
.type log10l,@function
log10l:
	fldlg2
	fldt 8(%rsp)
	fyl2x
	ret


text:
.global logl
.type logl,@function
logl:
	fldln2
	fldt 8(%rsp)
	fyl2x
	ret


text: # see floorl.s


text:
.global lrintf
.type lrintf,@function
lrintf:
	cvtss2si %xmm0,%rax
	ret


text:
.global llrint
.type llrint,@function
llrint:
	cvtsd2si %xmm0,%rax
	ret


text: # see exp2l.s


text:
.global log2l
.type log2l,@function
log2l:
	fld1
	fldt 8(%rsp)
	fyl2x
	ret


text:
.global asinl
.type asinl,@function
asinl:
	fldt 8(%rsp)
1:	fld %st(0)
	fld1
	fsub %st(0),%st(1)
	fadd %st(2)
	fmulp
	fsqrt
	fpatan
	ret


text:
.global fabs
.type fabs,@function
fabs:
	xor %eax,%eax
	dec %rax
	shr %rax
	movq %rax,%xmm1
	andpd %xmm1,%xmm0
	ret


text:
# exp(x) = 2^hi + 2^hi (2^lo - 1)
# where hi+lo = log2e*x with 128bit precision
# exact log2e*x calculation depends on nearest rounding mode
# using the exact multiplication method of Dekker and Veltkamp

.global expl
.type expl,@function
expl:
	fldt 8(%rsp)

		# interesting case: 0x1p-32 <= |x| < 16384
		# check if (exponent|0x8000) is in [0xbfff-32, 0xbfff+13]
	mov 16(%rsp), %ax
	or $0x8000, %ax
	sub $0xbfdf, %ax
	cmp $45, %ax
	jbe 2f
	test %ax, %ax
	fld1
	js 1f
		# if |x|>=0x1p14 or nan return 2^trunc(x)
	fscale
	fstp %st(1)
	ret
		# if |x|<0x1p-32 return 1+x
1:	faddp
	ret

		# should be 0x1.71547652b82fe178p0L == 0x3fff b8aa3b29 5c17f0bc
		# it will be wrong on non-nearest rounding mode
2:	fldl2e
	subq $48, %rsp
		# hi = log2e_hi*x
		# 2^hi = exp2l(hi)
	fmul %st(1),%st
	fld %st(0)
	fstpt (%rsp)
	fstpt 16(%rsp)
	fstpt 32(%rsp)
	call exp2l
		# if 2^hi == inf return 2^hi
	fld %st(0)
	fstpt (%rsp)
	cmpw $0x7fff, 8(%rsp)
	je 1f
	fldt 32(%rsp)
	fldt 16(%rsp)
		# fpu stack: 2^hi x hi
		# exact mult: x*log2e
	fld %st(1)
		# c = 0x1p32+1
	movq $0x41f0000000100000,%rax
	pushq %rax
	fldl (%rsp)
		# xh = x - c*x + c*x
		# xl = x - xh
	fmulp
	fld %st(2)
	fsub %st(1), %st
	faddp
	fld %st(2)
	fsub %st(1), %st
		# yh = log2e_hi - c*log2e_hi + c*log2e_hi
	movq $0x3ff7154765200000,%rax
	pushq %rax
	fldl (%rsp)
		# fpu stack: 2^hi x hi xh xl yh
		# lo = hi - xh*yh + xl*yh
	fld %st(2)
	fmul %st(1), %st
	fsubp %st, %st(4)
	fmul %st(1), %st
	faddp %st, %st(3)
		# yl = log2e_hi - yh
	movq $0x3de705fc2f000000,%rax
	pushq %rax
	fldl (%rsp)
		# fpu stack: 2^hi x lo xh xl yl
		# lo += xh*yl + xl*yl
	fmul %st, %st(2)
	fmulp %st, %st(1)
	fxch %st(2)
	faddp
	faddp
		# log2e_lo
	movq $0xbfbe,%rax
	pushq %rax
	movq $0x82f0025f2dc582ee,%rax
	pushq %rax
	fldt (%rsp)
	addq $40,%rsp
		# fpu stack: 2^hi x lo log2e_lo
		# lo += log2e_lo*x
		# return 2^hi + 2^hi (2^lo - 1)
	fmulp %st, %st(2)
	faddp
	f2xm1
	fmul %st(1), %st
	faddp
1:	addq $48, %rsp
	ret


text:
.global lrint
.type lrint,@function
lrint:
	cvtsd2si %xmm0,%rax
	ret


text:
.global fmodl
.type fmodl,@function
fmodl:
	fldt 24(%rsp)
	fldt 8(%rsp)
1:	fprem
	fstsw %ax
	sahf
	jp 1b
	fstp %st(1)
	ret


text:
.global atanl
.type atanl,@function
atanl:
	fldt 8(%rsp)
	fld1
	fpatan
	ret


text:
.global sqrt
.type sqrt,@function
sqrt:	sqrtsd %xmm0, %xmm0
	ret


text:
.global llrintf
.type llrintf,@function
llrintf:
	cvtss2si %xmm0,%rax
	ret


text:
.global atan2l
.type atan2l,@function
atan2l:
	fldt 8(%rsp)
	fldt 24(%rsp)
	fpatan
	ret


text:
.global fabsl
.type fabsl,@function
fabsl:
	fldt 8(%rsp)
	fabs
	ret


text:
.global llrintl
.type llrintl,@function
llrintl:
	fldt 8(%rsp)
	fistpll 8(%rsp)
	mov 8(%rsp),%rax
	ret


text:
.global remainderl
.type remainderl,@function
remainderl:
	fldt 24(%rsp)
	fldt 8(%rsp)
1:	fprem1
	fstsw %ax
	sahf
	jp 1b
	fstp %st(1)
	ret


text:
#include <mqueue.h>
#include "syscall.h"

ssize_t mq_timedreceive(mqd_t mqd, char *restrict msg, size_t len, unsigned *restrict prio, const struct timespec *restrict at)
{
	return syscall_cp(SYS_mq_timedreceive, mqd, msg, len, prio, at);
}


text:
#include <mqueue.h>
#include "syscall.h"

int mq_getattr(mqd_t mqd, struct mq_attr *attr)
{
	return mq_setattr(mqd, 0, attr);
}


text:
#include <mqueue.h>
#include "syscall.h"

int mq_timedsend(mqd_t mqd, const char *msg, size_t len, unsigned prio, const struct timespec *at)
{
	return syscall_cp(SYS_mq_timedsend, mqd, msg, len, prio, at);
}


text:
#include <mqueue.h>

int mq_send(mqd_t mqd, const char *msg, size_t len, unsigned prio)
{
	return mq_timedsend(mqd, msg, len, prio, 0);
}


text:
#include <mqueue.h>
#include "syscall.h"

int mq_setattr(mqd_t mqd, const struct mq_attr *restrict new, struct mq_attr *restrict old)
{
	return syscall(SYS_mq_getsetattr, mqd, new, old);
}


text:
#include <mqueue.h>
#include "syscall.h"

int mq_close(mqd_t mqd)
{
	return syscall(SYS_close, mqd);
}


text:
#include <mqueue.h>
#include <pthread.h>
#include <errno.h>
#include <sys/socket.h>
#include <signal.h>
#include <unistd.h>
#include "syscall.h"

struct args {
	pthread_barrier_t barrier;
	int sock;
	const struct sigevent *sev;
};

static void *start(void *p)
{
	struct args *args = p;
	char buf[32];
	ssize_t n;
	int s = args->sock;
	void (*func)(union sigval) = args->sev->sigev_notify_function;
	union sigval val = args->sev->sigev_value;

	pthread_barrier_wait(&args->barrier);
	n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
	close(s);
	if (n==sizeof buf && buf[sizeof buf - 1] == 1)
		func(val);
	return 0;
}

int mq_notify(mqd_t mqd, const struct sigevent *sev)
{
	struct args args = { .sev = sev };
	pthread_attr_t attr;
	pthread_t td;
	int s;
	struct sigevent sev2;
	static const char zeros[32];

	if (!sev || sev->sigev_notify != SIGEV_THREAD)
		return syscall(SYS_mq_notify, mqd, sev);

	s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0);
	if (s < 0) return -1;
	args.sock = s;

	if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes;
	else pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	pthread_barrier_init(&args.barrier, 0, 2);

	if (pthread_create(&td, &attr, start, &args)) {
		__syscall(SYS_close, s);
		errno = EAGAIN;
		return -1;
	}

	pthread_barrier_wait(&args.barrier);
	pthread_barrier_destroy(&args.barrier);

	sev2.sigev_notify = SIGEV_THREAD;
	sev2.sigev_signo = s;
	sev2.sigev_value.sival_ptr = (void *)&zeros;

	if (syscall(SYS_mq_notify, mqd, &sev2) < 0) {
		pthread_cancel(td);
		__syscall(SYS_close, s);
		return -1;
	}

	return 0;
}


text:
#include <mqueue.h>
#include <errno.h>
#include "syscall.h"

int mq_unlink(const char *name)
{
	int ret;
	if (*name == '/') name++;
	ret = __syscall(SYS_mq_unlink, name);
	if (ret < 0) {
		if (ret == -EPERM) ret = -EACCES;
		errno = -ret;
		return -1;
	}
	return ret;
}


text:
#include <mqueue.h>
#include <fcntl.h>
#include <stdarg.h>
#include "syscall.h"

mqd_t mq_open(const char *name, int flags, ...)
{
	mode_t mode = 0;
	struct mq_attr *attr = 0;
	if (*name == '/') name++;
	if (flags & O_CREAT) {
		va_list ap;
		va_start(ap, flags);
		mode = va_arg(ap, mode_t);
		attr = va_arg(ap, struct mq_attr *);
		va_end(ap);
	}
	return syscall(SYS_mq_open, name, flags, mode, attr);
}


text:
#include <mqueue.h>

ssize_t mq_receive(mqd_t mqd, char *msg, size_t len, unsigned *prio)
{
	return mq_timedreceive(mqd, msg, len, prio, 0);
}


text:
#include <fcntl.h>
#include <stdarg.h>
#include "syscall.h"
#include "libc.h"

int open(const char *filename, int flags, ...)
{
	mode_t mode = 0;

	if (flags & O_CREAT) {
		va_list ap;
		va_start(ap, flags);
		mode = va_arg(ap, mode_t);
		va_end(ap);
	}

	int fd = __sys_open_cp(filename, flags, mode);
	if (fd>=0 && (flags & O_CLOEXEC))
		__syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC);

	return __syscall_ret(fd);
}

LFS64(open);


text:
#include <fcntl.h>
#include <stdarg.h>
#include "syscall.h"
#include "libc.h"

int openat(int fd, const char *filename, int flags, ...)
{
	mode_t mode;
	va_list ap;
	va_start(ap, flags);
	mode = va_arg(ap, mode_t);
	va_end(ap);
	return syscall_cp(SYS_openat, fd, filename, flags|O_LARGEFILE, mode);
}

LFS64(openat);


text:
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include "syscall.h"
#include "libc.h"

int fcntl(int fd, int cmd, ...)
{
	unsigned long arg;
	va_list ap;
	va_start(ap, cmd);
	arg = va_arg(ap, unsigned long);
	va_end(ap);
	if (cmd == F_SETFL) arg |= O_LARGEFILE;
	if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg);
	if (cmd == F_GETOWN) {
		struct f_owner_ex ex;
		int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex);
		if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg);
		if (ret) return __syscall_ret(ret);
		return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid;
	}
	if (cmd == F_DUPFD_CLOEXEC) {
		int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
		if (ret != -EINVAL) {
			if (ret >= 0)
				__syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
			return __syscall_ret(ret);
		}
		ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0);
		if (ret != -EINVAL) {
			if (ret >= 0) __syscall(SYS_close, ret);
			return __syscall_ret(-EINVAL);
		}
		ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg);
		if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
		return __syscall_ret(ret);
	}
	switch (cmd) {
	case F_SETLK:
	case F_SETLKW:
	case F_GETLK:
	case F_GETOWN_EX:
	case F_SETOWN_EX:
		return syscall(SYS_fcntl, fd, cmd, (void *)arg);
	default:
		return syscall(SYS_fcntl, fd, cmd, arg);
	}
}


text:
#include <fcntl.h>
#include "syscall.h"
#include "libc.h"

int posix_fadvise(int fd, off_t base, off_t len, int advice)
{
	return -(__syscall)(SYS_fadvise, fd, __SYSCALL_LL_O(base),
		__SYSCALL_LL_E(len), advice);
}

LFS64(posix_fadvise);


text:
#include <fcntl.h>
#include "libc.h"

int creat(const char *filename, mode_t mode)
{
	return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode);
}

LFS64(creat);


text:
#include <fcntl.h>
#include "syscall.h"
#include "libc.h"

int posix_fallocate(int fd, off_t base, off_t len)
{
	return -__syscall(SYS_fallocate, fd, 0, __SYSCALL_LL_E(base),
		__SYSCALL_LL_E(len));
}

LFS64(posix_fallocate);


text:
#define _GNU_SOURCE
#include <sys/mman.h>
#include "syscall.h"

int posix_madvise(void *addr, size_t len, int advice)
{
	if (advice == MADV_DONTNEED) return 0;
	return -__syscall(SYS_madvise, addr, len, advice);
}


text:
#include <sys/mman.h>
#include "syscall.h"

int mlock(const void *addr, size_t len)
{
	return syscall(SYS_mlock, addr, len);
}


text:
#include <sys/mman.h>
#include "libc.h"
#include "syscall.h"

int __mprotect(void *addr, size_t len, int prot)
{
	size_t start, end;
	start = (size_t)addr & -PAGE_SIZE;
	end = (size_t)((char *)addr + len + PAGE_SIZE-1) & -PAGE_SIZE;
	return syscall(SYS_mprotect, start, end-start, prot);
}

weak_alias(__mprotect, mprotect);


text:
#include <unistd.h>
#include <sys/mman.h>
#include <stdarg.h>
#include "syscall.h"
#include "libc.h"

void *__mremap(void *old_addr, size_t old_len, size_t new_len, int flags, ...)
{
	va_list ap;
	void *new_addr;

	va_start(ap, flags);
	new_addr = va_arg(ap, void *);
	va_end(ap);

	return (void *)syscall(SYS_mremap, old_addr, old_len, new_len, flags, new_addr);
}

weak_alias(__mremap, mremap);


text:
#include <sys/mman.h>
#include "syscall.h"

int msync(void *start, size_t len, int flags)
{
	return syscall(SYS_msync, start, len, flags);
}


text:
#include <sys/mman.h>
#include "syscall.h"
#include "libc.h"

int __madvise(void *addr, size_t len, int advice)
{
	return syscall(SYS_madvise, addr, len, advice);
}

weak_alias(__madvise, madvise);


text:
#include <sys/mman.h>
#include "syscall.h"

int mlockall(int flags)
{
	return syscall(SYS_mlockall, flags);
}


text:
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <pthread.h>

char *__strchrnul(const char *, int);

char *__shm_mapname(const char *name, char *buf)
{
	char *p;
	while (*name == '/') name++;
	if (*(p = __strchrnul(name, '/')) || p==name ||
	    (p-name <= 2 && name[0]=='.' && p[-1]=='.')) {
		errno = EINVAL;
		return 0;
	}
	if (p-name > NAME_MAX) {
		errno = ENAMETOOLONG;
		return 0;
	}
	memcpy(buf, "/dev/shm/", 9);
	memcpy(buf+9, name, p-name+1);
	return buf;
}

int shm_open(const char *name, int flag, mode_t mode)
{
	int cs;
	char buf[NAME_MAX+10];
	if (!(name = __shm_mapname(name, buf))) return -1;
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
	int fd = open(name, flag|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK, mode);
	pthread_setcancelstate(cs, 0);
	return fd;
}

int shm_unlink(const char *name)
{
	char buf[NAME_MAX+10];
	if (!(name = __shm_mapname(name, buf))) return -1;
	return unlink(name);
}


text:
#define _GNU_SOURCE
#include <sys/mman.h>
#include "syscall.h"

int mincore (void *addr, size_t len, unsigned char *vec)
{
	return syscall(SYS_mincore, addr, len, vec);
}


text:
#include <sys/mman.h>
#include "syscall.h"

int munlock(const void *addr, size_t len)
{
	return syscall(SYS_munlock, addr, len);
}


text:
#include <sys/mman.h>
#include "syscall.h"

int munlockall(void)
{
	return syscall(SYS_munlockall);
}


text:
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdint.h>
#include <limits.h>
#include "syscall.h"
#include "libc.h"

static void dummy1(int x) { }
static void dummy0(void) { }
weak_alias(dummy1, __vm_lock);
weak_alias(dummy0, __vm_unlock);

#define UNIT SYSCALL_MMAP2_UNIT
#define OFF_MASK ((-0x2000ULL << (8*sizeof(long)-1)) | (UNIT-1))

void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
{
	if (off & OFF_MASK) {
		errno = EINVAL;
		return MAP_FAILED;
	}
	if (len >= PTRDIFF_MAX) {
		errno = ENOMEM;
		return MAP_FAILED;
	}
	if (flags & MAP_FIXED) {
		__vm_lock(-1);
		__vm_unlock();
	}
#ifdef SYS_mmap2
	return (void *)syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT);
#else
	return (void *)syscall(SYS_mmap, start, len, prot, flags, fd, off);
#endif
}

weak_alias(__mmap, mmap);

LFS64(mmap);


text:
#include <sys/mman.h>
#include "syscall.h"
#include "libc.h"

static void dummy1(int x) { }
static void dummy0(void) { }
weak_alias(dummy1, __vm_lock);
weak_alias(dummy0, __vm_unlock);

int __munmap(void *start, size_t len)
{
	int ret;
	__vm_lock(-1);
	__vm_unlock();
	ret = syscall(SYS_munmap, start, len);
	return ret;
}

weak_alias(__munmap, munmap);


text:
#include <aio.h>
#include "libc.h"

ssize_t aio_return(struct aiocb *cb)
{
	return cb->__ret;
}

LFS64(aio_return);


text:
#include <aio.h>
#include <errno.h>
#include "pthread_impl.h"
#include "libc.h"

/* Due to the requirement that aio_suspend be async-signal-safe, we cannot
 * use any locks, wait queues, etc. that would make it more efficient. The
 * only obviously-correct algorithm is to generate a wakeup every time any
 * aio operation finishes and have aio_suspend re-evaluate the completion
 * status of each aiocb it was waiting on. */

static volatile int seq;

void __aio_wake(void)
{
	a_inc(&seq);
	__wake(&seq, -1, 1);
}

int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts)
{
	int i, last, first=1, ret=0;
	struct timespec at;

	if (cnt<0) {
		errno = EINVAL;
		return -1;
	}

	for (;;) {
		last = seq;

		for (i=0; i<cnt; i++) {
			if (cbs[i] && cbs[i]->__err != EINPROGRESS)
				return 0;
		}

		if (first && ts) {
			clock_gettime(CLOCK_MONOTONIC, &at);
			at.tv_sec += ts->tv_sec;
			if ((at.tv_nsec += ts->tv_nsec) >= 1000000000) {
				at.tv_nsec -= 1000000000;
				at.tv_sec++;
			}
			first = 0;
		}

		ret = __timedwait(&seq, last, CLOCK_MONOTONIC,
			ts ? &at : 0, 0, 0, 1);

		if (ret == ETIMEDOUT) ret = EAGAIN;

		if (ret) {
			errno = ret;
			return -1;
		}
	}
}

LFS64(aio_suspend);


text:
#include <aio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "pthread_impl.h"
#include "libc.h"

static void dummy(void)
{
}

weak_alias(dummy, __aio_wake);

static void notify_signal(struct sigevent *sev)
{
	siginfo_t si = {
		.si_signo = sev->sigev_signo,
		.si_value = sev->sigev_value,
		.si_code = SI_ASYNCIO,
		.si_pid = getpid(),
		.si_uid = getuid()
	};
	__syscall(SYS_rt_sigqueueinfo, si.si_pid, si.si_signo, &si);
}

static void *io_thread(void *p)
{
	struct aiocb *cb = p;
	int fd = cb->aio_fildes;
	void *buf = (void *)cb->aio_buf;
	size_t len = cb->aio_nbytes;
	off_t off = cb->aio_offset;
	int op = cb->aio_lio_opcode;
	struct sigevent sev = cb->aio_sigevent;
	ssize_t ret;

	if (op == LIO_WRITE) {
		if (  (fcntl(fd, F_GETFL) & O_APPEND)
		    ||((ret = pwrite(fd, buf, len, off))<0 && errno==ESPIPE) )
			ret = write(fd, buf, len);
	} else if (op == LIO_READ) {
		if ( (ret = pread(fd, buf, len, off))<0 && errno==ESPIPE )
			ret = read(fd, buf, len);
	} else {
		ret = 0;
	}
	cb->__ret = ret;

	if (ret < 0) a_store(&cb->__err, errno);
	else a_store(&cb->__err, 0);

	__aio_wake();

	switch (sev.sigev_notify) {
	case SIGEV_SIGNAL:
		notify_signal(&sev);
		break;
	case SIGEV_THREAD:
		sev.sigev_notify_function(sev.sigev_value);
		break;
	}

	return 0;
}

static int new_req(struct aiocb *cb)
{
	int ret = 0;
	pthread_attr_t a;
	sigset_t set;
	pthread_t td;

	if (cb->aio_sigevent.sigev_notify == SIGEV_THREAD) {
		if (cb->aio_sigevent.sigev_notify_attributes)
			a = *cb->aio_sigevent.sigev_notify_attributes;
		else
			pthread_attr_init(&a);
	} else {
		pthread_attr_init(&a);
		pthread_attr_setstacksize(&a, PAGE_SIZE);
		pthread_attr_setguardsize(&a, 0);
	}
	pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
	sigfillset(&set);
	pthread_sigmask(SIG_BLOCK, &set, &set);
	cb->__err = EINPROGRESS;
	if (pthread_create(&td, &a, io_thread, cb)) {
		errno = EAGAIN;
		ret = -1;
	}
	pthread_sigmask(SIG_SETMASK, &set, 0);
	cb->__td = td;

	return ret;
}

int aio_read(struct aiocb *cb)
{
	cb->aio_lio_opcode = LIO_READ;
	return new_req(cb);
}

int aio_write(struct aiocb *cb)
{
	cb->aio_lio_opcode = LIO_WRITE;
	return new_req(cb);
}

LFS64(aio_read);
LFS64(aio_write);


text:
#include <aio.h>
#include <errno.h>
#include "libc.h"

int aio_fsync(int op, struct aiocb *cb)
{
	/* FIXME: unsupported */
	errno = EINVAL;
	return -1;
}

LFS64(aio_fsync);


text:
#include <aio.h>
#include "libc.h"

int aio_error(const struct aiocb *cb)
{
	return cb->__err;
}

LFS64(aio_error);


text:
#include <aio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include "pthread_impl.h"
#include "libc.h"

struct lio_state {
	struct sigevent *sev;
	int cnt;
	struct aiocb *cbs[];
};

static int lio_wait(struct lio_state *st)
{
	int i, err, got_err = 0;
	int cnt = st->cnt;
	struct aiocb **cbs = st->cbs;

	for (;;) {
		for (i=0; i<cnt; i++) {
			if (!cbs[i]) continue;
			err = aio_error(cbs[i]);
			if (err==EINPROGRESS)
				break;
			if (err) got_err=1;
			cbs[i] = 0;
		}
		if (i==cnt) {
			if (got_err) {
				errno = EIO;
				return -1;
			}
			return 0;
		}
		if (aio_suspend((void *)cbs, cnt, 0))
			return -1;
	}
}

static void notify_signal(struct sigevent *sev)
{
	siginfo_t si = {
		.si_signo = sev->sigev_signo,
		.si_value = sev->sigev_value,
		.si_code = SI_ASYNCIO,
		.si_pid = getpid(),
		.si_uid = getuid()
	};
	__syscall(SYS_rt_sigqueueinfo, si.si_pid, si.si_signo, &si);
}

static void *wait_thread(void *p)
{
	struct lio_state *st = p;
	struct sigevent *sev = st->sev;
	lio_wait(st);
	free(st);
	switch (sev->sigev_notify) {
	case SIGEV_SIGNAL:
		notify_signal(sev);
		break;
	case SIGEV_THREAD:
		sev->sigev_notify_function(sev->sigev_value);
		break;
	}
	return 0;
}

int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, struct sigevent *restrict sev)
{
	int i, ret;
	struct lio_state *st=0;

	if (cnt < 0) {
		errno = EINVAL;
		return -1;
	}

	if (mode == LIO_WAIT || (sev && sev->sigev_notify != SIGEV_NONE)) {
		if (!(st = malloc(sizeof *st + cnt*sizeof *cbs))) {
			errno = EAGAIN;
			return -1;
		}
		st->cnt = cnt;
		st->sev = sev;
		memcpy(st->cbs, (void*) cbs, cnt*sizeof *cbs);
	}

	for (i=0; i<cnt; i++) {
		if (!cbs[i]) continue;
		switch (cbs[i]->aio_lio_opcode) {
		case LIO_READ:
			ret = aio_read(cbs[i]);
			break;
		case LIO_WRITE:
			ret = aio_write(cbs[i]);
			break;
		default:
			continue;
		}
		if (ret) {
			free(st);
			errno = EAGAIN;
			return -1;
		}
	}

	if (mode == LIO_WAIT) {
		ret = lio_wait(st);
		free(st);
		return ret;
	}

	if (st) {
		pthread_attr_t a;
		sigset_t set;
		pthread_t td;

		if (sev->sigev_notify == SIGEV_THREAD) {
			if (sev->sigev_notify_attributes)
				a = *sev->sigev_notify_attributes;
			else
				pthread_attr_init(&a);
		} else {
			pthread_attr_init(&a);
			pthread_attr_setstacksize(&a, PAGE_SIZE);
			pthread_attr_setguardsize(&a, 0);
		}
		pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
		sigfillset(&set);
		pthread_sigmask(SIG_BLOCK, &set, &set);
		if (pthread_create(&td, &a, wait_thread, st)) {
			free(st);
			errno = EAGAIN;
			return -1;
		}
		pthread_sigmask(SIG_SETMASK, &set, 0);
	}

	return 0;
}

LFS64(lio_listio);


text:
#include <aio.h>
#include <pthread.h>
#include <errno.h>
#include "libc.h"

int aio_cancel(int fd, struct aiocb *cb)
{
	if (!cb) {
		/* FIXME: for correctness, we should return AIO_ALLDONE
		 * if there are no outstanding aio operations on this
		 * file descriptor, but that would require making aio
		 * much slower, and seems to have little advantage since
		 * we don't support cancellation anyway. */
		return AIO_NOTCANCELED;
	}
	return cb->__err==EINPROGRESS ? AIO_NOTCANCELED : AIO_ALLDONE;
}

LFS64(aio_cancel);


text:
#define _GNU_SOURCE
#include <string.h>

char *strsep(char **str, const char *sep)
{
	char *s = *str, *end;
	if (!s) return NULL;
	end = s + strcspn(s, sep);
	if (*end) *end++ = 0;
	else end = 0;
	*str = end;
	return s;
}


text:
#include <unistd.h>

void swab(const void *restrict _src, void *restrict _dest, ssize_t n)
{
	const char *src = _src;
	char *dest = _dest;
	for (; n>1; n-=2) {
		dest[0] = src[1];
		dest[1] = src[0];
		dest += 2;
		src += 2;
	}
}


text:
#include <string.h>

char *__stpcpy(char *, const char *);

char *strcpy(char *restrict dest, const char *restrict src)
{
#if 1
	__stpcpy(dest, src);
	return dest;
#else
	const unsigned char *s = src;
	unsigned char *d = dest;
	while ((*d++ = *s++));
	return dest;
#endif
}


text:
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "libc.h"

#define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

char *__stpcpy(char *restrict d, const char *restrict s)
{
	size_t *wd;
	const size_t *ws;

	if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
		for (; (uintptr_t)s % ALIGN; s++, d++)
			if (!(*d=*s)) return d;
		wd=(void *)d; ws=(const void *)s;
		for (; !HASZERO(*ws); *wd++ = *ws++);
		d=(void *)wd; s=(const void *)ws;
	}
	for (; (*d=*s); s++, d++);

	return d;
}

weak_alias(__stpcpy, stpcpy);


text:
#include <wchar.h>

wchar_t *wcscpy(wchar_t *restrict d, const wchar_t *restrict s)
{
	wchar_t *a = d;
	while ((*d++ = *s++));
	return a;
}


text:
#include <strings.h>
#include <ctype.h>
#include "libc.h"

int strcasecmp(const char *_l, const char *_r)
{
	const unsigned char *l=(void *)_l, *r=(void *)_r;
	for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++);
	return tolower(*l) - tolower(*r);
}

int __strcasecmp_l(const char *l, const char *r, locale_t loc)
{
	return strcasecmp(l, r);
}

weak_alias(__strcasecmp_l, strcasecmp_l);


text:
#define _GNU_SOURCE
#include <ctype.h>
#include <string.h>

int strverscmp(const char *l, const char *r)
{
	int haszero=1;
	while (*l==*r) {
		if (!*l) return 0;

		if (*l=='0') {
			if (haszero==1) {
				haszero=0;
			}
		} else if (isdigit(*l)) {
			if (haszero==1) {
				haszero=2;
			}
		} else {
			haszero=1;
		}
		l++; r++;
	}
	if (haszero==1 && (*l=='0' || *r=='0')) {
		haszero=0;
	}
	if ((isdigit(*l) && isdigit(*r) ) && haszero) {
		size_t lenl=0, lenr=0;
		while (isdigit(l[lenl]) ) lenl++;
		while (isdigit(r[lenr]) ) lenr++;
		if (lenl==lenr) {
			return (*l -  *r);
		} else if (lenl>lenr) {
			return 1;
		} else {
			return -1;
		}
	} else {
		return (*l -  *r);
	}
}


text:
#include <wchar.h>
#include <wctype.h>

int wcsncasecmp(const wchar_t *l, const wchar_t *r, size_t n)
{
	if (!n--) return 0;
	for (; *l && *r && n && (*l == *r || towlower(*l) == towlower(*r)); l++, r++, n--);
	return towlower(*l) - towlower(*r);
}


text:
#include <wchar.h>

wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n)
{
	wchar_t *d0 = d;
	if ((size_t)(d-s) < n)
		while (n--) d[n] = s[n];
	else
		while (n--) *d++ = *s++;
	return d0;
}


text:
#include <stdlib.h>
#include <string.h>
#include "libc.h"

char *__strdup(const char *s)
{
	size_t l = strlen(s);
	char *d = malloc(l+1);
	if (!d) return NULL;
	return memcpy(d, s, l+1);
}

weak_alias(__strdup, strdup);


text:
#include <wchar.h>

wchar_t *wcscat(wchar_t *restrict dest, const wchar_t *restrict src)
{
	wcscpy(dest + wcslen(dest), src);
	return dest;
}


text:
#include <string.h>

char *__stpncpy(char *, const char *, size_t);

char *strncpy(char *restrict d, const char *restrict s, size_t n)
{
	__stpncpy(d, s, n);
	return d;
}


text:
#include <string.h>

int memcmp(const void *vl, const void *vr, size_t n)
{
	const unsigned char *l=vl, *r=vr;
	for (; n && *l == *r; n--, l++, r++);
	return n ? *l-*r : 0;
}


text:
#include <stdlib.h>
#include <string.h>

char *strndup(const char *s, size_t n)
{
	size_t l = strnlen(s, n);
	char *d = malloc(l+1);
	if (!d) return NULL;
	memcpy(d, s, l);
	d[l] = 0;
	return d;
}


text:
#include <signal.h>
#include <string.h>
#include "locale_impl.h"

#if (SIGHUP == 1) && (SIGINT == 2) && (SIGQUIT == 3) && (SIGILL == 4) \
 && (SIGTRAP == 5) && (SIGABRT == 6) && (SIGBUS == 7) && (SIGFPE == 8) \
 && (SIGKILL == 9) && (SIGUSR1 == 10) && (SIGSEGV == 11) && (SIGUSR2 == 12) \
 && (SIGPIPE == 13) && (SIGALRM == 14) && (SIGTERM == 15) && (SIGSTKFLT == 16) \
 && (SIGCHLD == 17) && (SIGCONT == 18) && (SIGSTOP == 19) && (SIGTSTP == 20) \
 && (SIGTTIN == 21) && (SIGTTOU == 22) && (SIGURG == 23) && (SIGXCPU == 24) \
 && (SIGXFSZ == 25) && (SIGVTALRM == 26) && (SIGPROF == 27) && (SIGWINCH == 28) \
 && (SIGPOLL == 29) && (SIGPWR == 30) && (SIGSYS == 31)

#define sigmap(x) x

#else

static const char map[] = {
	[SIGHUP]    = 1,
	[SIGINT]    = 2,
	[SIGQUIT]   = 3,
	[SIGILL]    = 4,
	[SIGTRAP]   = 5,
	[SIGABRT]   = 6,
	[SIGBUS]    = 7,
	[SIGFPE]    = 8,
	[SIGKILL]   = 9,
	[SIGUSR1]   = 10,
	[SIGSEGV]   = 11,
	[SIGUSR2]   = 12,
	[SIGPIPE]   = 13,
	[SIGALRM]   = 14,
	[SIGTERM]   = 15,
	[SIGSTKFLT] = 16,
	[SIGCHLD]   = 17,
	[SIGCONT]   = 18,
	[SIGSTOP]   = 19,
	[SIGTSTP]   = 20,
	[SIGTTIN]   = 21,
	[SIGTTOU]   = 22,
	[SIGURG]    = 23,
	[SIGXCPU]   = 24,
	[SIGXFSZ]   = 25,
	[SIGVTALRM] = 26,
	[SIGPROF]   = 27,
	[SIGWINCH]  = 28,
	[SIGPOLL]   = 29,
	[SIGPWR]    = 30,
	[SIGSYS]    = 31
};

#define sigmap(x) ((x) >= sizeof map ? (x) : map[(x)])

#endif

static const char strings[] =
	"Unknown signal\0"
	"Hangup\0"
	"Interrupt\0"
	"Quit\0"
	"Illegal instruction\0"
	"Trace/breakpoint trap\0"
	"Aborted\0"
	"Bus error\0"
	"Arithmetic exception\0"
	"Killed\0"
	"User defined signal 1\0"
	"Segmentation fault\0"
	"User defined signal 2\0"
	"Broken pipe\0"
	"Alarm clock\0"
	"Terminated\0"
	"Stack fault\0"
	"Child process status\0"
	"Continued\0"
	"Stopped (signal)\0"
	"Stopped\0"
	"Stopped (tty input)\0"
	"Stopped (tty output)\0"
	"Urgent I/O condition\0"
	"CPU time limit exceeded\0"
	"File size limit exceeded\0"
	"Virtual timer expired\0"
	"Profiling timer expired\0"
	"Window changed\0"
	"I/O possible\0"
	"Power failure\0"
	"Bad system call\0"
	"RT32"
	"\0RT33\0RT34\0RT35\0RT36\0RT37\0RT38\0RT39\0RT40"
	"\0RT41\0RT42\0RT43\0RT44\0RT45\0RT46\0RT47\0RT48"
	"\0RT49\0RT50\0RT51\0RT52\0RT53\0RT54\0RT55\0RT56"
	"\0RT57\0RT58\0RT59\0RT60\0RT61\0RT62\0RT63\0RT64"
#if _NSIG > 65
	"\0RT65\0RT66\0RT67\0RT68\0RT69\0RT70\0RT71\0RT72"
	"\0RT73\0RT74\0RT75\0RT76\0RT77\0RT78\0RT79\0RT80"
	"\0RT81\0RT82\0RT83\0RT84\0RT85\0RT86\0RT87\0RT88"
	"\0RT89\0RT90\0RT91\0RT92\0RT93\0RT94\0RT95\0RT96"
	"\0RT97\0RT98\0RT99\0RT100\0RT101\0RT102\0RT103\0RT104"
	"\0RT105\0RT106\0RT107\0RT108\0RT109\0RT110\0RT111\0RT112"
	"\0RT113\0RT114\0RT115\0RT116\0RT117\0RT118\0RT119\0RT120"
	"\0RT121\0RT122\0RT123\0RT124\0RT125\0RT126\0RT127\0RT128"
#endif
	"";

char *strsignal(int signum)
{
	const char *s = strings;

	signum = sigmap(signum);
	if (signum - 1U >= _NSIG-1) signum = 0;

	for (; signum--; s++) for (; *s; s++);

	return (char *)LCTRANS_CUR(s);
}


text:
#define _BSD_SOURCE
#include <string.h>
#include <strings.h>

void bcopy(const void *s1, void *s2, size_t n)
{
	memmove(s2, s1, n);
}


text:
#include <wchar.h>

wchar_t *wcstok(wchar_t *restrict s, const wchar_t *restrict sep, wchar_t **restrict p)
{
	if (!s && !(s = *p)) return NULL;
	s += wcsspn(s, sep);
	if (!*s) return *p = 0;
	*p = s + wcscspn(s, sep);
	if (**p) *(*p)++ = 0;
	else *p = 0;
	return s;
}


text:
#include <string.h>
#include <stdint.h>
#include <endian.h>

void *memcpy(void *restrict dest, const void *restrict src, size_t n)
{
	unsigned char *d = dest;
	const unsigned char *s = src;

#ifdef __GNUC__

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LS >>
#define RS <<
#else
#define LS <<
#define RS >>
#endif

	typedef uint32_t __attribute__((__may_alias__)) u32;
	uint32_t w, x;

	for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++;

	if ((uintptr_t)d % 4 == 0) {
		for (; n>=16; s+=16, d+=16, n-=16) {
			*(u32 *)(d+0) = *(u32 *)(s+0);
			*(u32 *)(d+4) = *(u32 *)(s+4);
			*(u32 *)(d+8) = *(u32 *)(s+8);
			*(u32 *)(d+12) = *(u32 *)(s+12);
		}
		if (n&8) {
			*(u32 *)(d+0) = *(u32 *)(s+0);
			*(u32 *)(d+4) = *(u32 *)(s+4);
			d += 8; s += 8;
		}
		if (n&4) {
			*(u32 *)(d+0) = *(u32 *)(s+0);
			d += 4; s += 4;
		}
		if (n&2) {
			*d++ = *s++; *d++ = *s++;
		}
		if (n&1) {
			*d = *s;
		}
		return dest;
	}

	if (n >= 32) switch ((uintptr_t)d % 4) {
	case 1:
		w = *(u32 *)s;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		n -= 3;
		for (; n>=17; s+=16, d+=16, n-=16) {
			x = *(u32 *)(s+1);
			*(u32 *)(d+0) = (w LS 24) | (x RS 8);
			w = *(u32 *)(s+5);
			*(u32 *)(d+4) = (x LS 24) | (w RS 8);
			x = *(u32 *)(s+9);
			*(u32 *)(d+8) = (w LS 24) | (x RS 8);
			w = *(u32 *)(s+13);
			*(u32 *)(d+12) = (x LS 24) | (w RS 8);
		}
		break;
	case 2:
		w = *(u32 *)s;
		*d++ = *s++;
		*d++ = *s++;
		n -= 2;
		for (; n>=18; s+=16, d+=16, n-=16) {
			x = *(u32 *)(s+2);
			*(u32 *)(d+0) = (w LS 16) | (x RS 16);
			w = *(u32 *)(s+6);
			*(u32 *)(d+4) = (x LS 16) | (w RS 16);
			x = *(u32 *)(s+10);
			*(u32 *)(d+8) = (w LS 16) | (x RS 16);
			w = *(u32 *)(s+14);
			*(u32 *)(d+12) = (x LS 16) | (w RS 16);
		}
		break;
	case 3:
		w = *(u32 *)s;
		*d++ = *s++;
		n -= 1;
		for (; n>=19; s+=16, d+=16, n-=16) {
			x = *(u32 *)(s+3);
			*(u32 *)(d+0) = (w LS 8) | (x RS 24);
			w = *(u32 *)(s+7);
			*(u32 *)(d+4) = (x LS 8) | (w RS 24);
			x = *(u32 *)(s+11);
			*(u32 *)(d+8) = (w LS 8) | (x RS 24);
			w = *(u32 *)(s+15);
			*(u32 *)(d+12) = (x LS 8) | (w RS 24);
		}
		break;
	}
	if (n&16) {
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
	}
	if (n&8) {
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
	}
	if (n&4) {
		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
	}
	if (n&2) {
		*d++ = *s++; *d++ = *s++;
	}
	if (n&1) {
		*d = *s;
	}
	return dest;
#endif

	for (; n; n--) *d++ = *s++;
	return dest;
}


text:
#define _BSD_SOURCE
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "libc.h"

#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

size_t strlcpy(char *d, const char *s, size_t n)
{
	char *d0 = d;
	size_t *wd;
	const size_t *ws;

	if (!n--) goto finish;
	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
		if (n && *s) {
			wd=(void *)d; ws=(const void *)s;
			for (; n>=sizeof(size_t) && !HASZERO(*ws);
			       n-=sizeof(size_t), ws++, wd++) *wd = *ws;
			d=(void *)wd; s=(const void *)ws;
		}
	}
	for (; n && (*d=*s); n--, s++, d++);
	*d = 0;
finish:
	return d-d0 + strlen(s);
}


text:
#include <wchar.h>

int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n)
{
	for (; n && *l==*r; n--, l++, r++);
	return n ? *l-*r : 0;
}


text:
#define _GNU_SOURCE
#include <string.h>

char *strcasestr(const char *h, const char *n)
{
	size_t l = strlen(n);
	for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h;
	return 0;
}


text:
#define _BSD_SOURCE
#include <string.h>

size_t strlcat(char *d, const char *s, size_t n)
{
	size_t l = strnlen(d, n);
	if (l == n) return l + strlen(s);
	return l + strlcpy(d+l, s, n-l);
}


text:
#include <string.h>
#include <errno.h>
#include "libc.h"

int strerror_r(int err, char *buf, size_t buflen)
{
	char *msg = strerror(err);
	size_t l = strlen(msg);
	if (l >= buflen) {
		if (buflen) {
			memcpy(buf, msg, buflen-1);
			buf[buflen-1] = 0;
		}
		return ERANGE;
	}
	memcpy(buf, msg, l+1);
	return 0;
}

weak_alias(strerror_r, __xpg_strerror_r);


text:
#include <wchar.h>

int wcsncasecmp_l(const wchar_t *l, const wchar_t *r, size_t n, locale_t locale)
{
	return wcsncasecmp(l, r, n);
}


text:
#include <wchar.h>

wchar_t *wcsrchr(const wchar_t *s, wchar_t c)
{
	const wchar_t *p;
	for (p=s+wcslen(s); p>=s && *p!=c; p--);
	return p>=s ? (wchar_t *)p : 0;
}


text:
#include <wchar.h>

wchar_t *wcpncpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
{
	return wcsncpy(d, s, n) + wcsnlen(s, n);
}


text:
#include <string.h>
#include <stdint.h>

static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
{
	uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
	for (h++; *h && hw != nw; hw = hw<<8 | *++h);
	return *h ? (char *)h-1 : 0;
}

static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
{
	uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
	uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
	for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
	return *h ? (char *)h-2 : 0;
}

static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
{
	uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
	uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
	for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
	return *h ? (char *)h-3 : 0;
}

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
{
	const unsigned char *z;
	size_t l, ip, jp, k, p, ms, p0, mem, mem0;
	size_t byteset[32 / sizeof(size_t)] = { 0 };
	size_t shift[256];

	/* Computing length of needle and fill shift table */
	for (l=0; n[l] && h[l]; l++)
		BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
	if (n[l]) return 0; /* hit the end of h */

	/* Compute maximal suffix */
	ip = -1; jp = 0; k = p = 1;
	while (jp+k<l) {
		if (n[ip+k] == n[jp+k]) {
			if (k == p) {
				jp += p;
				k = 1;
			} else k++;
		} else if (n[ip+k] > n[jp+k]) {
			jp += k;
			k = 1;
			p = jp - ip;
		} else {
			ip = jp++;
			k = p = 1;
		}
	}
	ms = ip;
	p0 = p;

	/* And with the opposite comparison */
	ip = -1; jp = 0; k = p = 1;
	while (jp+k<l) {
		if (n[ip+k] == n[jp+k]) {
			if (k == p) {
				jp += p;
				k = 1;
			} else k++;
		} else if (n[ip+k] < n[jp+k]) {
			jp += k;
			k = 1;
			p = jp - ip;
		} else {
			ip = jp++;
			k = p = 1;
		}
	}
	if (ip+1 > ms+1) ms = ip;
	else p = p0;

	/* Periodic needle? */
	if (memcmp(n, n+p, ms+1)) {
		mem0 = 0;
		p = MAX(ms, l-ms-1) + 1;
	} else mem0 = l-p;
	mem = 0;

	/* Initialize incremental end-of-haystack pointer */
	z = h;

	/* Search loop */
	for (;;) {
		/* Update incremental end-of-haystack pointer */
		if (z-h < l) {
			/* Fast estimate for MIN(l,63) */
			size_t grow = l | 63;
			const unsigned char *z2 = memchr(z, 0, grow);
			if (z2) {
				z = z2;
				if (z-h < l) return 0;
			} else z += grow;
		}

		/* Check last byte first; advance by shift on mismatch */
		if (BITOP(byteset, h[l-1], &)) {
			k = l-shift[h[l-1]];
			//printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l);
			if (k) {
				if (mem0 && mem && k < p) k = l-p;
				h += k;
				mem = 0;
				continue;
			}
		} else {
			h += l;
			mem = 0;
			continue;
		}

		/* Compare right half */
		for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
		if (n[k]) {
			h += k-ms;
			mem = 0;
			continue;
		}
		/* Compare left half */
		for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
		if (k <= mem) return (char *)h;
		h += p;
		mem = mem0;
	}
}

char *strstr(const char *h, const char *n)
{
	/* Return immediately on empty needle */
	if (!n[0]) return (char *)h;

	/* Use faster algorithms for short needles */
	h = strchr(h, *n);
	if (!h || !n[1]) return (char *)h;
	if (!h[1]) return 0;
	if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
	if (!h[2]) return 0;
	if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
	if (!h[3]) return 0;
	if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);

	return twoway_strstr((void *)h, (void *)n);
}


text:
#include <wchar.h>

int wcscasecmp_l(const wchar_t *l, const wchar_t *r, locale_t locale)
{
	return wcscasecmp(l, r);
}


text:
#include <wchar.h>

wchar_t *wcschr(const wchar_t *s, wchar_t c)
{
	if (!c) return (wchar_t *)s + wcslen(s);
	for (; *s && *s != c; s++);
	return *s ? (wchar_t *)s : 0;
}


text:
#include <string.h>
#include "libc.h"

void *__memrchr(const void *m, int c, size_t n)
{
	const unsigned char *s = m;
	c = (unsigned char)c;
	while (n--) if (s[n]==c) return (void *)(s+n);
	return 0;
}

weak_alias(__memrchr, memrchr);


text:
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "libc.h"

#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

char *__stpncpy(char *restrict d, const char *restrict s, size_t n)
{
	size_t *wd;
	const size_t *ws;

	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
		if (!n || !*s) goto tail;
		wd=(void *)d; ws=(const void *)s;
		for (; n>=sizeof(size_t) && !HASZERO(*ws);
		       n-=sizeof(size_t), ws++, wd++) *wd = *ws;
		d=(void *)wd; s=(const void *)ws;
	}
	for (; n && (*d=*s); n--, s++, d++);
tail:
	memset(d, 0, n);
	return d;
}

weak_alias(__stpncpy, stpncpy);


text:
#include <wchar.h>

wchar_t *wcsncat(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
{
	wchar_t *a = d;
	d += wcslen(d);
	while (n && *s) n--, *d++ = *s++;
	*d++ = 0;
	return a;
}


text:
#include <wchar.h>

wchar_t *wmemcpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
{
	wchar_t *a = d;
	while (n--) *d++ = *s++;
	return a;
}


text:
#include <wchar.h>

wchar_t *wcswcs(const wchar_t *haystack, const wchar_t *needle)
{
	return wcsstr(haystack, needle);
}


text:
#include <string.h>

char *strcat(char *restrict dest, const char *restrict src)
{
	strcpy(dest + strlen(dest), src);
	return dest;
}


text:
#define _BSD_SOURCE
#include <string.h>
#include <strings.h>

char *index(const char *s, int c)
{
	return strchr(s, c);
}


text:
#include <wchar.h>

wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b)
{
	s += wcscspn(s, b);
	return *s ? (wchar_t *)s : NULL;
}


text:
#include <wchar.h>
#include <wctype.h>

int wcscasecmp(const wchar_t *l, const wchar_t *r)
{
	return wcsncasecmp(l, r, -1);
}


text:
#include <string.h>

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

size_t strspn(const char *s, const char *c)
{
	const char *a = s;
	size_t byteset[32/sizeof(size_t)] = { 0 };

	if (!c[0]) return 0;
	if (!c[1]) {
		for (; *s == *c; s++);
		return s-a;
	}

	for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
	for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
	return s-a;
}


text:
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "libc.h"

#define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

char *__strchrnul(const char *s, int c)
{
	size_t *w, k;

	c = (unsigned char)c;
	if (!c) return (char *)s + strlen(s);

	for (; (uintptr_t)s % ALIGN; s++)
		if (!*s || *(unsigned char *)s == c) return (char *)s;
	k = ONES * c;
	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
	for (s = (void *)w; *s && *(unsigned char *)s != c; s++);
	return (char *)s;
}

weak_alias(__strchrnul, strchrnul);


text:
#include <string.h>
#include <stdint.h>

void *memset(void *dest, int c, size_t n)
{
	unsigned char *s = dest;
	size_t k;

	/* Fill head and tail with minimal branching. Each
	 * conditional ensures that all the subsequently used
	 * offsets are well-defined and in the dest region. */

	if (!n) return dest;
	s[0] = s[n-1] = c;
	if (n <= 2) return dest;
	s[1] = s[n-2] = c;
	s[2] = s[n-3] = c;
	if (n <= 6) return dest;
	s[3] = s[n-4] = c;
	if (n <= 8) return dest;

	/* Advance pointer to align it at a 4-byte boundary,
	 * and truncate n to a multiple of 4. The previous code
	 * already took care of any head/tail that get cut off
	 * by the alignment. */

	k = -(uintptr_t)s & 3;
	s += k;
	n -= k;
	n &= -4;

#ifdef __GNUC__
	typedef uint32_t __attribute__((__may_alias__)) u32;
	typedef uint64_t __attribute__((__may_alias__)) u64;

	u32 c32 = ((u32)-1)/255 * (unsigned char)c;

	/* In preparation to copy 32 bytes at a time, aligned on
	 * an 8-byte bounary, fill head/tail up to 28 bytes each.
	 * As in the initial byte-based head/tail fill, each
	 * conditional below ensures that the subsequent offsets
	 * are valid (e.g. !(n<=24) implies n>=28). */

	*(u32 *)(s+0) = c32;
	*(u32 *)(s+n-4) = c32;
	if (n <= 8) return dest;
	*(u32 *)(s+4) = c32;
	*(u32 *)(s+8) = c32;
	*(u32 *)(s+n-12) = c32;
	*(u32 *)(s+n-8) = c32;
	if (n <= 24) return dest;
	*(u32 *)(s+12) = c32;
	*(u32 *)(s+16) = c32;
	*(u32 *)(s+20) = c32;
	*(u32 *)(s+24) = c32;
	*(u32 *)(s+n-28) = c32;
	*(u32 *)(s+n-24) = c32;
	*(u32 *)(s+n-20) = c32;
	*(u32 *)(s+n-16) = c32;

	/* Align to a multiple of 8 so we can fill 64 bits at a time,
	 * and avoid writing the same bytes twice as much as is
	 * practical without introducing additional branching. */

	k = 24 + ((uintptr_t)s & 4);
	s += k;
	n -= k;

	/* If this loop is reached, 28 tail bytes have already been
	 * filled, so any remainder when n drops below 32 can be
	 * safely ignored. */

	u64 c64 = c32 | ((u64)c32 << 32);
	for (; n >= 32; n-=32, s+=32) {
		*(u64 *)(s+0) = c64;
		*(u64 *)(s+8) = c64;
		*(u64 *)(s+16) = c64;
		*(u64 *)(s+24) = c64;
	}
#else
	/* Pure C fallback with no aliasing violations. */
	for (; n; n--, s++) *s = c;
#endif

	return dest;
}


text:
#define _BSD_SOURCE
#include <string.h>
#include <strings.h>

void bzero(void *s, size_t n)
{
	memset(s, 0, n);
}


text:
#define _BSD_SOURCE
#include <string.h>
#include <strings.h>

int bcmp(const void *s1, const void *s2, size_t n)
{
	return memcmp(s1, s2, n);
}


text:
#include <string.h>

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

char *__strchrnul(const char *, int);

size_t strcspn(const char *s, const char *c)
{
	const char *a = s;
	size_t byteset[32/sizeof(size_t)];

	if (!c[0] || !c[1]) return __strchrnul(s, *c)-a;

	memset(byteset, 0, sizeof byteset);
	for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
	for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++);
	return s-a;
}


text:
#include <wchar.h>

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))

static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
{
	const wchar_t *z;
	size_t l, ip, jp, k, p, ms, p0, mem, mem0;

	/* Computing length of needle */
	for (l=0; n[l] && h[l]; l++);
	if (n[l]) return 0; /* hit the end of h */

	/* Compute maximal suffix */
	ip = -1; jp = 0; k = p = 1;
	while (jp+k<l) {
		if (n[ip+k] == n[jp+k]) {
			if (k == p) {
				jp += p;
				k = 1;
			} else k++;
		} else if (n[ip+k] > n[jp+k]) {
			jp += k;
			k = 1;
			p = jp - ip;
		} else {
			ip = jp++;
			k = p = 1;
		}
	}
	ms = ip;
	p0 = p;

	/* And with the opposite comparison */
	ip = -1; jp = 0; k = p = 1;
	while (jp+k<l) {
		if (n[ip+k] == n[jp+k]) {
			if (k == p) {
				jp += p;
				k = 1;
			} else k++;
		} else if (n[ip+k] < n[jp+k]) {
			jp += k;
			k = 1;
			p = jp - ip;
		} else {
			ip = jp++;
			k = p = 1;
		}
	}
	if (ip+1 > ms+1) ms = ip;
	else p = p0;

	/* Periodic needle? */
	if (wmemcmp(n, n+p, ms+1)) {
		mem0 = 0;
		p = MAX(ms, l-ms-1) + 1;
	} else mem0 = l-p;
	mem = 0;

	/* Initialize incremental end-of-haystack pointer */
	z = h;

	/* Search loop */
	for (;;) {
		/* Update incremental end-of-haystack pointer */
		if (z-h < l) {
			/* Fast estimate for MIN(l,63) */
			size_t grow = l | 63;
			const wchar_t *z2 = wmemchr(z, 0, grow);
			if (z2) {
				z = z2;
				if (z-h < l) return 0;
			} else z += grow;
		}

		/* Compare right half */
		for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
		if (n[k]) {
			h += k-ms;
			mem = 0;
			continue;
		}
		/* Compare left half */
		for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
		if (k <= mem) return (wchar_t *)h;
		h += p;
		mem = mem0;
	}
}

wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n)
{
	/* Return immediately on empty needle or haystack */
	if (!n[0]) return (wchar_t *)h;
	if (!h[0]) return 0;

	/* Use faster algorithms for short needles */
	h = wcschr(h, *n);
	if (!h || !n[1]) return (wchar_t *)h;
	if (!h[1]) return 0;

	return twoway_wcsstr(h, n);
}


text:
#include <string.h>

char *strtok_r(char *restrict s, const char *restrict sep, char **restrict p)
{
	if (!s && !(s = *p)) return NULL;
	s += strspn(s, sep);
	if (!*s) return *p = 0;
	*p = s + strcspn(s, sep);
	if (**p) *(*p)++ = 0;
	else *p = 0;
	return s;
}


text:
#include <wchar.h>

int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n)
{
	for (; n && *l==*r && *l && *r; n--, l++, r++);
	return n ? *l - *r : 0;
}


text:
#include <wchar.h>

wchar_t *wcpcpy(wchar_t *restrict d, const wchar_t *restrict s)
{
	return wcscpy(d, s) + wcslen(s);
}


text:
#include <string.h>
#include <stdint.h>
#include <limits.h>

#define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

size_t strlen(const char *s)
{
	const char *a = s;
	const size_t *w;
	for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
	for (w = (const void *)s; !HASZERO(*w); w++);
	for (s = (const void *)w; *s; s++);
	return s-a;
}


text:
#include <wchar.h>

wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n)
{
	for (; n && *s != c; n--, s++);
	return n ? (wchar_t *)s : 0;
}


text:
#include <string.h>

char *strtok(char *restrict s, const char *restrict sep)
{
	static char *p;
	if (!s && !(s = p)) return NULL;
	s += strspn(s, sep);
	if (!*s) return p = 0;
	p = s + strcspn(s, sep);
	if (*p) *p++ = 0;
	else p = 0;
	return s;
}


text:
#include <string.h>
#include <stdint.h>

#define WT size_t
#define WS (sizeof(WT))

void *memmove(void *dest, const void *src, size_t n)
{
	char *d = dest;
	const char *s = src;

	if (d==s) return d;
	if (s+n <= d || d+n <= s) return memcpy(d, s, n);

	if (d<s) {
		if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
			while ((uintptr_t)d % WS) {
				if (!n--) return dest;
				*d++ = *s++;
			}
			for (; n>=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(WT *)s;
		}
		for (; n; n--) *d++ = *s++;
	} else {
		if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
			while ((uintptr_t)(d+n) % WS) {
				if (!n--) return dest;
				d[n] = s[n];
			}
			while (n>=WS) n-=WS, *(WT *)(d+n) = *(WT *)(s+n);
		}
		while (n) n--, d[n] = s[n];
	}

	return dest;
}


text:
#include <wchar.h>

size_t wcsnlen(const wchar_t *s, size_t n)
{
	const wchar_t *z = wmemchr(s, 0, n);
	if (z) n = z-s;
	return n;
}


text:
#include <string.h>

char *strncat(char *restrict d, const char *restrict s, size_t n)
{
	char *a = d;
	d += strlen(d);
	while (n && *s) n--, *d++ = *s++;
	*d++ = 0;
	return a;
}


text:
#include <string.h>
#include <stdint.h>
#include <limits.h>

#define SS (sizeof(size_t))
#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

void *memchr(const void *src, int c, size_t n)
{
	const unsigned char *s = src;
	c = (unsigned char)c;
	for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
	if (n && *s != c) {
		const size_t *w;
		size_t k = ONES * c;
		for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
		for (s = (const void *)w; n && *s != c; s++, n--);
	}
	return n ? (void *)s : 0;
}


text:
#include <string.h>
#include <stdint.h>
#include <limits.h>

#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
{
	unsigned char *d = dest;
	const unsigned char *s = src;
	size_t *wd, k;
	const size_t *ws;

	c = (unsigned char)c;
	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++);
		if ((uintptr_t)s & ALIGN) goto tail;
		k = ONES * c;
		wd=(void *)d; ws=(const void *)s;
		for (; n>=sizeof(size_t) && !HASZERO(*ws^k);
		       n-=sizeof(size_t), ws++, wd++) *wd = *ws;
		d=(void *)wd; s=(const void *)ws;
	}
	for (; n && (*d=*s)!=c; n--, s++, d++);
tail:
	if (*s==c) return d+1;
	return 0;
}


text:
#include <wchar.h>

size_t wcscspn(const wchar_t *s, const wchar_t *c)
{
	const wchar_t *a;
	if (!c[0]) return wcslen(s);
	if (!c[1]) return (s=wcschr(a=s, *c)) ? s-a : wcslen(a);
	for (a=s; *s && !wcschr(c, *s); s++);
	return s-a;
}


text:
#include <strings.h>
#include <ctype.h>
#include "libc.h"

int strncasecmp(const char *_l, const char *_r, size_t n)
{
	const unsigned char *l=(void *)_l, *r=(void *)_r;
	if (!n--) return 0;
	for (; *l && *r && n && (*l == *r || tolower(*l) == tolower(*r)); l++, r++, n--);
	return tolower(*l) - tolower(*r);
}

int __strncasecmp_l(const char *l, const char *r, size_t n, locale_t loc)
{
	return strncasecmp(l, r, n);
}

weak_alias(__strncasecmp_l, strncasecmp_l);


text:
#define _GNU_SOURCE
#include <string.h>

void *mempcpy(void *dest, const void *src, size_t n)
{
	return (char *)memcpy(dest, src, n) + n;
}


text:
#include <wchar.h>

wchar_t *wcsncpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
{
	wchar_t *a = d;
	while (n && *s) n--, *d++ = *s++;
	wmemset(d, 0, n);
	return a;
}


text:
#include <string.h>

char *strpbrk(const char *s, const char *b)
{
	s += strcspn(s, b);
	return *s ? (char *)s : 0;
}


text:
#include <string.h>

int strncmp(const char *_l, const char *_r, size_t n)
{
	const unsigned char *l=(void *)_l, *r=(void *)_r;
	if (!n--) return 0;
	for (; *l && *r && n && *l == *r ; l++, r++, n--);
	return *l - *r;
}


text:
#include <wchar.h>

int wcscmp(const wchar_t *l, const wchar_t *r)
{
	for (; *l==*r && *l && *r; l++, r++);
	return *l - *r;
}


text:
#include <string.h>

size_t strnlen(const char *s, size_t n)
{
	const char *p = memchr(s, 0, n);
	return p ? p-s : n;
}


text:
#include <wchar.h>

size_t wcslen(const wchar_t *s)
{
	const wchar_t *a;
	for (a=s; *s; s++);
	return s-a;
}


text:
#define _BSD_SOURCE
#include <string.h>
#include <strings.h>

char *rindex(const char *s, int c)
{
	return strrchr(s, c);
}


text:
#include <wchar.h>

size_t wcsspn(const wchar_t *s, const wchar_t *c)
{
	const wchar_t *a;
	for (a=s; *s && wcschr(c, *s); s++);
	return s-a;
}


text:
#include <string.h>

void *__memrchr(const void *, int, size_t);

char *strrchr(const char *s, int c)
{
	return __memrchr(s, c, strlen(s) + 1);
}


text:
#define _GNU_SOURCE
#include <string.h>
#include <stdint.h>

static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
	uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
	for (h++, k--; k; k--, hw = hw<<8 | *++h)
		if (hw == nw) return (char *)h-1;
	return 0;
}

static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
	uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
	uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
	for (h+=2, k-=2; k; k--, hw = (hw|*++h)<<8)
		if (hw == nw) return (char *)h-2;
	return 0;
}

static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
	uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
	uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
	for (h+=3, k-=3; k; k--, hw = hw<<8 | *++h)
		if (hw == nw) return (char *)h-3;
	return 0;
}

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l)
{
	size_t i, ip, jp, k, p, ms, p0, mem, mem0;
	size_t byteset[32 / sizeof(size_t)] = { 0 };
	size_t shift[256];

	/* Computing length of needle and fill shift table */
	for (i=0; i<l; i++)
		BITOP(byteset, n[i], |=), shift[n[i]] = i+1;

	/* Compute maximal suffix */
	ip = -1; jp = 0; k = p = 1;
	while (jp+k<l) {
		if (n[ip+k] == n[jp+k]) {
			if (k == p) {
				jp += p;
				k = 1;
			} else k++;
		} else if (n[ip+k] > n[jp+k]) {
			jp += k;
			k = 1;
			p = jp - ip;
		} else {
			ip = jp++;
			k = p = 1;
		}
	}
	ms = ip;
	p0 = p;

	/* And with the opposite comparison */
	ip = -1; jp = 0; k = p = 1;
	while (jp+k<l) {
		if (n[ip+k] == n[jp+k]) {
			if (k == p) {
				jp += p;
				k = 1;
			} else k++;
		} else if (n[ip+k] < n[jp+k]) {
			jp += k;
			k = 1;
			p = jp - ip;
		} else {
			ip = jp++;
			k = p = 1;
		}
	}
	if (ip+1 > ms+1) ms = ip;
	else p = p0;

	/* Periodic needle? */
	if (memcmp(n, n+p, ms+1)) {
		mem0 = 0;
		p = MAX(ms, l-ms-1) + 1;
	} else mem0 = l-p;
	mem = 0;

	/* Search loop */
	for (;;) {
		/* If remainder of haystack is shorter than needle, done */
		if (z-h < l) return 0;

		/* Check last byte first; advance by shift on mismatch */
		if (BITOP(byteset, h[l-1], &)) {
			k = l-shift[h[l-1]];
			if (k) {
				if (mem0 && mem && k < p) k = l-p;
				h += k;
				mem = 0;
				continue;
			}
		} else {
			h += l;
			mem = 0;
			continue;
		}

		/* Compare right half */
		for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
		if (k < l) {
			h += k-ms;
			mem = 0;
			continue;
		}
		/* Compare left half */
		for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
		if (k <= mem) return (char *)h;
		h += p;
		mem = mem0;
	}
}

void *memmem(const void *h0, size_t k, const void *n0, size_t l)
{
	const unsigned char *h = h0, *n = n0;

	/* Return immediately on empty needle */
	if (!l) return (void *)h;

	/* Return immediately when needle is longer than haystack */
	if (k<l) return 0;

	/* Use faster algorithms for short needles */
	h = memchr(h0, *n, k);
	if (!h || l==1) return (void *)h;
	k -= h - (const unsigned char *)h0;
	if (l==2) return twobyte_memmem(h, k, n);
	if (l==3) return threebyte_memmem(h, k, n);
	if (l==4) return fourbyte_memmem(h, k, n);

	return twoway_memmem(h, h+k, n, l);
}


text:
#include <stdlib.h>
#include <wchar.h>
#include "libc.h"

wchar_t *wcsdup(const wchar_t *s)
{
	size_t l = wcslen(s);
	wchar_t *d = malloc((l+1)*sizeof(wchar_t));
	if (!d) return NULL;
	return wmemcpy(d, s, l+1);
}


text:
#include <string.h>

int strcmp(const char *l, const char *r)
{
	for (; *l==*r && *l; l++, r++);
	return *(unsigned char *)l - *(unsigned char *)r;
}


text:
#include <wchar.h>

wchar_t *wmemset(wchar_t *d, wchar_t c, size_t n)
{
	wchar_t *ret = d;
	while (n--) *d++ = c;
	return ret;
}


text:
#include <string.h>

char *__strchrnul(const char *, int);

char *strchr(const char *s, int c)
{
	char *r = __strchrnul(s, c);
	return *(unsigned char *)r == (unsigned char)c ? r : 0;
}


text:
.global memcpy
.type memcpy,@function
memcpy:
	push %esi
	push %edi
	mov 12(%esp),%edi
	mov 16(%esp),%esi
	mov 20(%esp),%ecx
	mov %edi,%eax
	cmp $4,%ecx
	jc 1f
	test $3,%edi
	jz 1f
2:	movsb
	dec %ecx
	test $3,%edi
	jnz 2b
1:	mov %ecx,%edx
	shr $2,%ecx
	rep
	movsl
	and $3,%edx
	jz 1f
2:	movsb
	dec %edx
	jnz 2b
1:	pop %edi
	pop %esi
	ret


text:
.global memset
.type memset,@function
memset:
	mov 8(%esp),%al
	push %edi
	mov %al,%ah
	mov %al,%dl
	mov 16(%esp),%ecx
	shl $16,%eax
	mov 8(%esp),%edi
	mov %dl,%al
	mov %dl,%ah
	cmp $16,%ecx
	jb 1f

	mov %eax,-4(%edi,%ecx)
	shr $2,%ecx
	rep
	stosl
	mov 8(%esp),%eax
	pop %edi
	ret

1:	test %ecx,%ecx
	jz 1f

	mov %al,(%edi)
	mov %al,-1(%edi,%ecx)
	cmp $2,%ecx
	jbe 1f

	mov %al,1(%edi)
	mov %al,-2(%edi,%ecx)
	cmp $4,%ecx
	jbe 1f

	mov %eax,(%edi)
	mov %eax,-4(%edi,%ecx)
	cmp $8,%ecx
	jbe 1f

	mov %eax,4(%edi)
	mov %eax,-8(%edi,%ecx)

1:	mov 8(%esp),%eax
	pop %edi
	ret


text:
.global memmove
.type memmove,@function
memmove:
	mov 4(%esp),%eax
	sub 8(%esp),%eax
	cmp 12(%esp),%eax
	jae memcpy
	push %esi
	push %edi
	mov 12(%esp),%edi
	mov 16(%esp),%esi
	mov 20(%esp),%ecx
	lea -1(%edi,%ecx),%edi
	lea -1(%esi,%ecx),%esi
	std
	rep movsb
	cld
	lea 1(%edi),%eax
	pop %edi
	pop %esi
	ret


text:
.global memcpy
.type memcpy,@function
memcpy:
	mov %rdi,%rax
	cmp $8,%rdx
	jc 1f
	test $7,%edi
	jz 1f
2:	movsb
	dec %rdx
	test $7,%edi
	jnz 2b
1:	mov %rdx,%rcx
	shr $3,%rcx
	rep
	movsq
	and $7,%edx
	jz 1f
2:	movsb
	dec %edx
	jnz 2b
1:	ret


text:
.global memset
.type memset,@function
memset:
	and $0xff,%esi
	mov $0x101010101010101,%rax
	mov %rdx,%rcx
	mov %rdi,%r8
	imul %rsi,%rax
	cmp $16,%rcx
	jb 1f

	mov %rax,-8(%rdi,%rcx)
	shr $3,%rcx
	rep
	stosq
	mov %r8,%rax
	ret

1:	test %ecx,%ecx
	jz 1f

	mov %al,(%rdi)
	mov %al,-1(%rdi,%rcx)
	cmp $2,%ecx
	jbe 1f

	mov %al,1(%rdi)
	mov %al,-2(%rdi,%rcx)
	cmp $4,%ecx
	jbe 1f

	mov %eax,(%rdi)
	mov %eax,-4(%rdi,%rcx)
	cmp $8,%ecx
	jbe 1f

	mov %eax,4(%rdi)
	mov %eax,-8(%rdi,%rcx)

1:	mov %r8,%rax
	ret


text:
.global memmove
.type memmove,@function
memmove:
	mov %rdi,%rax
	sub %rsi,%rax
	cmp %rdx,%rax
	jae memcpy
	mov %rdx,%rcx
	lea -1(%rdi,%rdx),%rdi
	lea -1(%rsi,%rdx),%rsi
	std
	rep movsb
	cld
	lea 1(%rdi),%rax
	ret


text:
/*
 * Copyright (C) 2008 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
 * COPYRIGHT OWNER 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.
 */

/*
 * Optimized memcpy() for ARM.
 *
 * note that memcpy() always returns the destination pointer,
 * so we have to preserve R0.
  */

/*
 * This file has been modified from the original for use in musl libc.
 * The main changes are: addition of .type memcpy,%function to make the
 * code safely callable from thumb mode, adjusting the return
 * instructions to be compatible with pre-thumb ARM cpus, and removal
 * of prefetch code that is not compatible with older cpus.
 */

.global memcpy
.type memcpy,%function
memcpy:
	/* The stack must always be 64-bits aligned to be compliant with the
	 * ARM ABI. Since we have to save R0, we might as well save R4
	 * which we can use for better pipelining of the reads below
	 */
        .fnstart
        .save       {r0, r4, lr}
        stmfd       sp!, {r0, r4, lr}
        /* Making room for r5-r11 which will be spilled later */
        .pad        #28
        sub         sp, sp, #28

        /* it simplifies things to take care of len<4 early */
        cmp	r2, #4
        blo	copy_last_3_and_return

        /* compute the offset to align the source
         * offset = (4-(src&3))&3 = -src & 3
         */
        rsb	r3, r1, #0
        ands	r3, r3, #3
        beq	src_aligned

        /* align source to 32 bits. We need to insert 2 instructions between
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
         * stall 2 cycles.
         */
        movs	r12, r3, lsl #31
        sub	r2, r2, r3		/* we know that r3 <= r2 because r2 >= 4 */
        ldrmib	r3, [r1], #1
        ldrcsb	r4, [r1], #1
        ldrcsb	r12,[r1], #1
        strmib	r3, [r0], #1
        strcsb	r4, [r0], #1
        strcsb	r12,[r0], #1

src_aligned:

	/* see if src and dst are aligned together (congruent) */
	eor	r12, r0, r1
        tst	r12, #3
        bne	non_congruent

        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
         * frame. Don't update sp.
         */
        stmea	sp, {r5-r11}

        /* align the destination to a cache-line */
        rsb	r3, r0, #0
        ands	r3, r3, #0x1C
        beq    	congruent_aligned32
        cmp    	r3, r2
        andhi	r3, r2, #0x1C

        /* conditionnaly copies 0 to 7 words (length in r3) */
        movs	r12, r3, lsl #28
        ldmcsia	r1!, {r4, r5, r6, r7}	/* 16 bytes */
        ldmmiia	r1!, {r8, r9}			/*  8 bytes */
        stmcsia	r0!, {r4, r5, r6, r7}
        stmmiia	r0!, {r8, r9}
        tst    	r3, #0x4
        ldrne	r10,[r1], #4			/*  4 bytes */
        strne	r10,[r0], #4
        sub    	r2, r2, r3

congruent_aligned32:
	/*
 	 * here source is aligned to 32 bytes.
 	 */

cached_aligned32:
        subs   	r2, r2, #32
        blo    	less_than_32_left

        /*
         * We preload a cache-line up to 64 bytes ahead. On the 926, this will
         * stall only until the requested world is fetched, but the linefill
         * continues in the the background.
         * While the linefill is going, we write our previous cache-line
         * into the write-buffer (which should have some free space).
         * When the linefill is done, the writebuffer will
         * start dumping its content into memory
         *
         * While all this is going, we then load a full cache line into
         * 8 registers, this cache line should be in the cache by now
         * (or partly in the cache).
         *
         * This code should work well regardless of the source/dest alignment.
         *
         */

        /* Align the preload register to a cache-line because the cpu does
         * "critical word first" (the first word requested is loaded first).
         */
        @ bic    	r12, r1, #0x1F
        @ add    	r12, r12, #64

1:      ldmia  	r1!, { r4-r11 }
        subs   	r2, r2, #32

        /*
         * NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
         * for ARM9 preload will not be safely guarded by the preceding subs.
         * When it is safely guarded the only possibility to have SIGSEGV here
         * is because the caller overstates the length.
         */
        @ ldrhi  	r3, [r12], #32      /* cheap ARM9 preload */
        stmia  	r0!, { r4-r11 }
	bhs    	1b

        add	r2, r2, #32

less_than_32_left:
	/*
	 * less than 32 bytes left at this point (length in r2)
	 */

	/* skip all this if there is nothing to do, which should
	 * be a common case (if not executed the code below takes
	 * about 16 cycles)
	 */
	tst	r2, #0x1F
        beq	1f

        /* conditionnaly copies 0 to 31 bytes */
        movs	r12, r2, lsl #28
        ldmcsia	r1!, {r4, r5, r6, r7}	/* 16 bytes */
        ldmmiia	r1!, {r8, r9}			/*  8 bytes */
        stmcsia	r0!, {r4, r5, r6, r7}
        stmmiia	r0!, {r8, r9}
        movs	r12, r2, lsl #30
        ldrcs	r3, [r1], #4			/*  4 bytes */
        ldrmih	r4, [r1], #2			/*  2 bytes */
        strcs	r3, [r0], #4
        strmih	r4, [r0], #2
        tst    	r2, #0x1
        ldrneb	r3, [r1]				/*  last byte  */
        strneb	r3, [r0]

        /* we're done! restore everything and return */
1:	ldmfd	sp!, {r5-r11}
        ldmfd	sp!, {r0, r4, lr}
        tst	lr, #1
        moveq	pc, lr
        bx	lr

	/********************************************************************/

non_congruent:
	/*
	 * here source is aligned to 4 bytes
	 * but destination is not.
	 *
	 * in the code below r2 is the number of bytes read
	 * (the number of bytes written is always smaller, because we have
	 * partial words in the shift queue)
	 */
	cmp	r2, #4
	blo	copy_last_3_and_return

        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
         * frame. Don't update sp.
         */
        stmea	sp, {r5-r11}

        /* compute shifts needed to align src to dest */
        rsb	r5, r0, #0
        and	r5, r5, #3			/* r5 = # bytes in partial words */
        mov	r12, r5, lsl #3		/* r12 = right */
        rsb	lr, r12, #32		/* lr = left  */

        /* read the first word */
        ldr	r3, [r1], #4
        sub	r2, r2, #4

        /* write a partial word (0 to 3 bytes), such that destination
         * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
         */
        movs	r5, r5, lsl #31
        strmib	r3, [r0], #1
        movmi	r3, r3, lsr #8
        strcsb	r3, [r0], #1
        movcs	r3, r3, lsr #8
        strcsb	r3, [r0], #1
        movcs	r3, r3, lsr #8

        cmp	r2, #4
        blo	partial_word_tail

        /* Align destination to 32 bytes (cache line boundary) */
1:	tst	r0, #0x1c
        beq	2f
        ldr	r5, [r1], #4
        sub    	r2, r2, #4
        orr	r4, r3, r5,		lsl lr
        mov	r3, r5,			lsr r12
        str	r4, [r0], #4
        cmp    	r2, #4
        bhs	1b
        blo	partial_word_tail

	/* copy 32 bytes at a time */
2:	subs	r2, r2, #32
	blo	less_than_thirtytwo

        /* Use immediate mode for the shifts, because there is an extra cycle
         * for register shifts, which could account for up to 50% of
         * performance hit.
         */

        cmp	r12, #24
        beq	loop24
        cmp	r12, #8
        beq	loop8

loop16:
        ldr    	r12, [r1], #4
1:      mov    	r4, r12
	ldmia	r1!, {   r5,r6,r7,  r8,r9,r10,r11}
        subs   	r2, r2, #32
        ldrhs  	r12, [r1], #4
	orr	r3, r3, r4, lsl #16
        mov	r4, r4, lsr #16
        orr	r4, r4, r5, lsl #16
        mov	r5, r5, lsr #16
        orr	r5, r5, r6, lsl #16
        mov	r6, r6, lsr #16
        orr	r6, r6, r7, lsl #16
        mov	r7, r7, lsr #16
        orr	r7, r7, r8, lsl #16
        mov	r8, r8, lsr #16
        orr	r8, r8, r9, lsl #16
        mov	r9, r9, lsr #16
        orr	r9, r9, r10, lsl #16
        mov	r10, r10,		lsr #16
        orr	r10, r10, r11, lsl #16
        stmia	r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
        mov	r3, r11, lsr #16
        bhs	1b
        b	less_than_thirtytwo

loop8:
        ldr    	r12, [r1], #4
1:      mov    	r4, r12
	ldmia	r1!, {   r5,r6,r7,  r8,r9,r10,r11}
	subs	r2, r2, #32
        ldrhs  	r12, [r1], #4
        orr	r3, r3, r4, lsl #24
        mov	r4, r4, lsr #8
        orr	r4, r4, r5, lsl #24
        mov	r5, r5, lsr #8
        orr	r5, r5, r6, lsl #24
        mov	r6, r6,	 lsr #8
        orr	r6, r6, r7, lsl #24
        mov	r7, r7,	 lsr #8
        orr	r7, r7, r8,		lsl #24
        mov	r8, r8,	 lsr #8
        orr	r8, r8, r9,		lsl #24
        mov	r9, r9,	 lsr #8
        orr	r9, r9, r10,	lsl #24
        mov	r10, r10, lsr #8
        orr	r10, r10, r11,	lsl #24
        stmia	r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
        mov	r3, r11, lsr #8
        bhs	1b
        b	less_than_thirtytwo

loop24:
        ldr    	r12, [r1], #4
1:      mov    	r4, r12
	ldmia	r1!, {   r5,r6,r7,  r8,r9,r10,r11}
        subs	r2, r2, #32
        ldrhs  	r12, [r1], #4
        orr	r3, r3, r4, lsl #8
        mov	r4, r4, lsr #24
        orr	r4, r4, r5, lsl #8
        mov	r5, r5, lsr #24
        orr	r5, r5, r6, lsl #8
        mov	r6, r6, lsr #24
        orr	r6, r6, r7, lsl #8
        mov	r7, r7, lsr #24
        orr	r7, r7, r8, lsl #8
        mov	r8, r8, lsr #24
        orr	r8, r8, r9, lsl #8
        mov	r9, r9, lsr #24
        orr	r9, r9, r10, lsl #8
        mov	r10, r10, lsr #24
        orr	r10, r10, r11, lsl #8
        stmia	r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
        mov	r3, r11, lsr #24
        bhs	1b

less_than_thirtytwo:
	/* copy the last 0 to 31 bytes of the source */
	rsb	r12, lr, #32		/* we corrupted r12, recompute it  */
        add	r2, r2, #32
        cmp	r2, #4
        blo	partial_word_tail

1:	ldr	r5, [r1], #4
        sub    	r2, r2, #4
        orr	r4, r3, r5,		lsl lr
        mov	r3,	r5,			lsr r12
        str	r4, [r0], #4
        cmp    	r2, #4
        bhs	1b

partial_word_tail:
	/* we have a partial word in the input buffer */
	movs	r5, lr, lsl #(31-3)
	strmib	r3, [r0], #1
        movmi	r3, r3, lsr #8
        strcsb	r3, [r0], #1
        movcs	r3, r3, lsr #8
        strcsb	r3, [r0], #1

        /* Refill spilled registers from the stack. Don't update sp. */
        ldmfd	sp, {r5-r11}

copy_last_3_and_return:
	movs	r2, r2, lsl #31	/* copy remaining 0, 1, 2 or 3 bytes */
        ldrmib	r2, [r1], #1
        ldrcsb	r3, [r1], #1
        ldrcsb	r12,[r1]
        strmib	r2, [r0], #1
        strcsb	r3, [r0], #1
        strcsb	r12,[r0]

        /* we're done! restore sp and spilled registers and return */
        add    	sp,  sp, #28
        ldmfd	sp!, {r0, r4, lr}
        tst	lr, #1
        moveq	pc, lr
        bx	lr


text: memcpy.s


text:
int abs(int a)
{
	return a>0 ? a : -a;
}


text:
long labs(long a)
{
	return a>0 ? a : -a;
}


text:
#include <inttypes.h>

intmax_t imaxabs(intmax_t a)
{
	return a>0 ? a : -a;
}


text:
#include <inttypes.h>

imaxdiv_t imaxdiv(intmax_t num, intmax_t den)
{
	return (imaxdiv_t){ num/den, num%den };
}


text:
#include <stdlib.h>

lldiv_t lldiv(long long num, long long den)
{
	return (lldiv_t){ num/den, num%den };
}


text:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *fcvt(double x, int n, int *dp, int *sign)
{
	char tmp[1500];
	int i, lz;

	if (n > 1400U) n = 1400;
	sprintf(tmp, "%.*f", n, x);
	i = (tmp[0] == '-');
	if (tmp[i] == '0') lz = strspn(tmp+i+2, "0");
	else lz = -(int)strcspn(tmp+i, ".");

	if (n<=lz) {
		*sign = i;
		*dp = 1;
		if (n>14U) n = 14;
		return "000000000000000"+14-n;
	}

	return ecvt(x, n-lz, dp, sign);
}


text:
#include <stdlib.h>

div_t div(int num, int den)
{
	return (div_t){ num/den, num%den };
}


text:
#include <stdlib.h>

double atof(const char *s)
{
	return strtod(s, 0);
}


text:
#include <stdlib.h>

ldiv_t ldiv(long num, long den)
{
	return (ldiv_t){ num/den, num%den };
}


text:
#include <stdlib.h>
#include "shgetc.h"
#include "floatscan.h"
#include "stdio_impl.h"
#include "libc.h"

static long double strtox(const char *s, char **p, int prec)
{
	FILE f = {
		.buf = (void *)s, .rpos = (void *)s,
		.rend = (void *)-1, .lock = -1
	};
	shlim(&f, 0);
	long double y = __floatscan(&f, prec, 1);
	off_t cnt = shcnt(&f);
	if (p) *p = cnt ? (char *)s + cnt : (char *)s;
	return y;
}

float strtof(const char *restrict s, char **restrict p)
{
	return strtox(s, p, 0);
}

double strtod(const char *restrict s, char **restrict p)
{
	return strtox(s, p, 1);
}

long double strtold(const char *restrict s, char **restrict p)
{
	return strtox(s, p, 2);
}

weak_alias(strtof, strtof_l);
weak_alias(strtod, strtod_l);
weak_alias(strtold, strtold_l);
weak_alias(strtof, __strtof_l);
weak_alias(strtod, __strtod_l);
weak_alias(strtold, __strtold_l);


text:
long long llabs(long long a)
{
	return a>0 ? a : -a;
}


text:
#include "stdio_impl.h"
#include "intscan.h"
#include "shgetc.h"
#include <inttypes.h>
#include <limits.h>
#include <wctype.h>
#include <wchar.h>

/* This read function heavily cheats. It knows:
 *  (1) len will always be 1
 *  (2) non-ascii characters don't matter */

static size_t do_read(FILE *f, unsigned char *buf, size_t len)
{
	size_t i;
	const wchar_t *wcs = f->cookie;

	if (!wcs[0]) wcs=L"@";
	for (i=0; i<f->buf_size && wcs[i]; i++)
		f->buf[i] = wcs[i] < 128 ? wcs[i] : '@';
	f->rpos = f->buf;
	f->rend = f->buf + i;
	f->cookie = (void *)(wcs+i);

	if (i && len) {
		*buf = *f->rpos++;
		return 1;
	}
	return 0;
}

static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsigned long long lim)
{
	wchar_t *t = (wchar_t *)s;
	unsigned char buf[64];
	FILE f = {0};
	f.flags = 0;
	f.rpos = f.rend = 0;
	f.buf = buf + 4;
	f.buf_size = sizeof buf - 4;
	f.lock = -1;
	f.read = do_read;
	while (iswspace(*t)) t++;
	f.cookie = (void *)t;
	shlim(&f, 0);
	unsigned long long y = __intscan(&f, base, 1, lim);
	if (p) {
		size_t cnt = shcnt(&f);
		*p = cnt ? t + cnt : (wchar_t *)s;
	}
	return y;
}

unsigned long long wcstoull(const wchar_t *restrict s, wchar_t **restrict p, int base)
{
	return wcstox(s, p, base, ULLONG_MAX);
}

long long wcstoll(const wchar_t *restrict s, wchar_t **restrict p, int base)
{
	return wcstox(s, p, base, LLONG_MIN);
}

unsigned long wcstoul(const wchar_t *restrict s, wchar_t **restrict p, int base)
{
	return wcstox(s, p, base, ULONG_MAX);
}

long wcstol(const wchar_t *restrict s, wchar_t **restrict p, int base)
{
	return wcstox(s, p, base, 0UL+LONG_MIN);
}

intmax_t wcstoimax(const wchar_t *restrict s, wchar_t **restrict p, int base)
{
	return wcstoll(s, p, base);
}

uintmax_t wcstoumax(const wchar_t *restrict s, wchar_t **restrict p, int base)
{
	return wcstoull(s, p, base);
}


text:
#include "shgetc.h"
#include "floatscan.h"
#include "stdio_impl.h"
#include <wchar.h>
#include <wctype.h>

/* This read function heavily cheats. It knows:
 *  (1) len will always be 1
 *  (2) non-ascii characters don't matter */

static size_t do_read(FILE *f, unsigned char *buf, size_t len)
{
	size_t i;
	const wchar_t *wcs = f->cookie;

	if (!wcs[0]) wcs=L"@";
	for (i=0; i<f->buf_size && wcs[i]; i++)
		f->buf[i] = wcs[i] < 128 ? wcs[i] : '@';
	f->rpos = f->buf;
	f->rend = f->buf + i;
	f->cookie = (void *)(wcs+i);

	if (i && len) {
		*buf = *f->rpos++;
		return 1;
	}
	return 0;
}

static long double wcstox(const wchar_t *s, wchar_t **p, int prec)
{
	wchar_t *t = (wchar_t *)s;
	unsigned char buf[64];
	FILE f = {0};
	f.flags = 0;
	f.rpos = f.rend = 0;
	f.buf = buf + 4;
	f.buf_size = sizeof buf - 4;
	f.lock = -1;
	f.read = do_read;
	while (iswspace(*t)) t++;
	f.cookie = (void *)t;
	shlim(&f, 0);
	long double y = __floatscan(&f, prec, 1);
	if (p) {
		size_t cnt = shcnt(&f);
		*p = cnt ? t + cnt : (wchar_t *)s;
	}
	return y;
}

float wcstof(const wchar_t *restrict s, wchar_t **restrict p)
{
	return wcstox(s, p, 0);
}

double wcstod(const wchar_t *restrict s, wchar_t **restrict p)
{
	return wcstox(s, p, 1);
}

long double wcstold(const wchar_t *restrict s, wchar_t **restrict p)
{
	return wcstox(s, p, 2);
}


text:
#include <stdlib.h>

void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
{
	void *try;
	int sign;
	while (nel > 0) {
		try = (char *)base + width*(nel/2);
		sign = cmp(key, try);
		if (!sign) return try;
		else if (nel == 1) break;
		else if (sign < 0)
			nel /= 2;
		else {
			base = try;
			nel -= nel/2;
		}
	}
	return NULL;
}


text:
/* Copyright (C) 2011 by Valentin Ochs
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "atomic.h"
#define ntz(x) a_ctz_l((x))

typedef int (*cmpfun)(const void *, const void *);

static inline int pntz(size_t p[2]) {
	int r = ntz(p[0] - 1);
	if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
		return r;
	}
	return 0;
}

static void cycle(size_t width, unsigned char* ar[], int n)
{
	unsigned char tmp[256];
	size_t l;
	int i;

	if(n < 2) {
		return;
	}

	ar[n] = tmp;
	while(width) {
		l = sizeof(tmp) < width ? sizeof(tmp) : width;
		memcpy(ar[n], ar[0], l);
		for(i = 0; i < n; i++) {
			memcpy(ar[i], ar[i + 1], l);
			ar[i] += l;
		}
		width -= l;
	}
}

/* shl() and shr() need n > 0 */
static inline void shl(size_t p[2], int n)
{
	if(n >= 8 * sizeof(size_t)) {
		n -= 8 * sizeof(size_t);
		p[1] = p[0];
		p[0] = 0;
	}
	p[1] <<= n;
	p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
	p[0] <<= n;
}

static inline void shr(size_t p[2], int n)
{
	if(n >= 8 * sizeof(size_t)) {
		n -= 8 * sizeof(size_t);
		p[0] = p[1];
		p[1] = 0;
	}
	p[0] >>= n;
	p[0] |= p[1] << (sizeof(size_t) * 8 - n);
	p[1] >>= n;
}

static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size_t lp[])
{
	unsigned char *rt, *lf;
	unsigned char *ar[14 * sizeof(size_t) + 1];
	int i = 1;

	ar[0] = head;
	while(pshift > 1) {
		rt = head - width;
		lf = head - width - lp[pshift - 2];

		if((*cmp)(ar[0], lf) >= 0 && (*cmp)(ar[0], rt) >= 0) {
			break;
		}
		if((*cmp)(lf, rt) >= 0) {
			ar[i++] = lf;
			head = lf;
			pshift -= 1;
		} else {
			ar[i++] = rt;
			head = rt;
			pshift -= 2;
		}
	}
	cycle(width, ar, i);
}

static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[])
{
	unsigned char *stepson,
	              *rt, *lf;
	size_t p[2];
	unsigned char *ar[14 * sizeof(size_t) + 1];
	int i = 1;
	int trail;

	p[0] = pp[0];
	p[1] = pp[1];

	ar[0] = head;
	while(p[0] != 1 || p[1] != 0) {
		stepson = head - lp[pshift];
		if((*cmp)(stepson, ar[0]) <= 0) {
			break;
		}
		if(!trusty && pshift > 1) {
			rt = head - width;
			lf = head - width - lp[pshift - 2];
			if((*cmp)(rt, stepson) >= 0 || (*cmp)(lf, stepson) >= 0) {
				break;
			}
		}

		ar[i++] = stepson;
		head = stepson;
		trail = pntz(p);
		shr(p, trail);
		pshift += trail;
		trusty = 0;
	}
	if(!trusty) {
		cycle(width, ar, i);
		sift(head, width, cmp, pshift, lp);
	}
}

void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
{
	size_t lp[12*sizeof(size_t)];
	size_t i, size = width * nel;
	unsigned char *head, *high;
	size_t p[2] = {1, 0};
	int pshift = 1;
	int trail;

	if (!size) return;

	head = base;
	high = head + size - width;

	/* Precompute Leonardo numbers, scaled by element width */
	for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++);

	while(head < high) {
		if((p[0] & 3) == 3) {
			sift(head, width, cmp, pshift, lp);
			shr(p, 2);
			pshift += 2;
		} else {
			if(lp[pshift - 1] >= high - head) {
				trinkle(head, width, cmp, p, pshift, 0, lp);
			} else {
				sift(head, width, cmp, pshift, lp);
			}

			if(pshift == 1) {
				shl(p, 1);
				pshift = 0;
			} else {
				shl(p, pshift - 1);
				pshift = 1;
			}
		}

		p[0] |= 1;
		head += width;
	}

	trinkle(head, width, cmp, p, pshift, 0, lp);

	while(pshift != 1 || p[0] != 1 || p[1] != 0) {
		if(pshift <= 1) {
			trail = pntz(p);
			shr(p, trail);
			pshift += trail;
		} else {
			shl(p, 2);
			pshift -= 2;
			p[0] ^= 7;
			shr(p, 1);
			trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp);
			shl(p, 1);
			p[0] |= 1;
			trinkle(head - width, width, cmp, p, pshift, 1, lp);
		}
		head -= width;
	}
}


text:
#include <stdlib.h>
#include <ctype.h>

long long atoll(const char *s)
{
	long long n=0;
	int neg=0;
	while (isspace(*s)) s++;
	switch (*s) {
	case '-': neg=1;
	case '+': s++;
	}
	/* Compute n as a negative number to avoid overflow on LLONG_MIN */
	while (isdigit(*s))
		n = 10*n - (*s++ - '0');
	return neg ? n : -n;
}


text:
#include <stdlib.h>
#include <ctype.h>

long atol(const char *s)
{
	long n=0;
	int neg=0;
	while (isspace(*s)) s++;
	switch (*s) {
	case '-': neg=1;
	case '+': s++;
	}
	/* Compute n as a negative number to avoid overflow on LONG_MIN */
	while (isdigit(*s))
		n = 10*n - (*s++ - '0');
	return neg ? n : -n;
}


text:
#include "stdio_impl.h"
#include "intscan.h"
#include "shgetc.h"
#include <inttypes.h>
#include <limits.h>
#include <ctype.h>
#include "libc.h"

static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim)
{
	/* FIXME: use a helper function or macro to setup the FILE */
	FILE f;
	f.flags = 0;
	f.buf = f.rpos = (void *)s;
	if ((size_t)s > (size_t)-1/2)
		f.rend = (void *)-1;
	else
		f.rend = (unsigned char *)s+(size_t)-1/2;
	f.lock = -1;
	shlim(&f, 0);
	unsigned long long y = __intscan(&f, base, 1, lim);
	if (p) {
		size_t cnt = shcnt(&f);
		*p = (char *)s + cnt;
	}
	return y;
}

unsigned long long strtoull(const char *restrict s, char **restrict p, int base)
{
	return strtox(s, p, base, ULLONG_MAX);
}

long long strtoll(const char *restrict s, char **restrict p, int base)
{
	return strtox(s, p, base, LLONG_MIN);
}

unsigned long strtoul(const char *restrict s, char **restrict p, int base)
{
	return strtox(s, p, base, ULONG_MAX);
}

long strtol(const char *restrict s, char **restrict p, int base)
{
	return strtox(s, p, base, 0UL+LONG_MIN);
}

intmax_t strtoimax(const char *restrict s, char **restrict p, int base)
{
	return strtoll(s, p, base);
}

uintmax_t strtoumax(const char *restrict s, char **restrict p, int base)
{
	return strtoull(s, p, base);
}

weak_alias(strtol, __strtol_internal);
weak_alias(strtoul, __strtoul_internal);
weak_alias(strtoll, __strtoll_internal);
weak_alias(strtoull, __strtoull_internal);
weak_alias(strtoimax, __strtoimax_internal);
weak_alias(strtoumax, __strtoumax_internal);


text:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>

char *gcvt(double x, int n, char *b)
{
	sprintf(b, "%.*g", n, x);
	return b;
}


text:
#include <stdlib.h>
#include <ctype.h>

int atoi(const char *s)
{
	int n=0, neg=0;
	while (isspace(*s)) s++;
	switch (*s) {
	case '-': neg=1;
	case '+': s++;
	}
	/* Compute n as a negative number to avoid overflow on INT_MIN */
	while (isdigit(*s))
		n = 10*n - (*s++ - '0');
	return neg ? n : -n;
}


text:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>

char *ecvt(double x, int n, int *dp, int *sign)
{
	static char buf[16];
	char tmp[32];
	int i, j;

	if (n-1U > 15) n = 15;
	sprintf(tmp, "%.*e", n-1, x);
	i = *sign = (tmp[0]=='-');
	for (j=0; tmp[i]!='e'; j+=(tmp[i++]!='.'))
		buf[j] = tmp[i];
	buf[j] = 0;
	*dp = atoi(tmp+i+1)+1;

	return buf;
}


text:
#include <errno.h>
#include "syscall.h"

long __syscall_ret(unsigned long r)
{
	if (r > -4096UL) {
		errno = -r;
		return -1;
	}
	return r;
}


text:
/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */
/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

#ifndef _LIBM_H
#define _LIBM_H

#include <stdint.h>
#include <float.h>
#include <math.h>
#include <complex.h>
#include <endian.h>

#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN
union ldshape {
	long double f;
	struct {
		uint64_t m;
		uint16_t se;
	} i;
};
#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN
union ldshape {
	long double f;
	struct {
		uint64_t lo;
		uint32_t mid;
		uint16_t top;
		uint16_t se;
	} i;
	struct {
		uint64_t lo;
		uint64_t hi;
	} i2;
};
#else
#error Unsupported long double representation
#endif

#define FORCE_EVAL(x) do {                        \
	if (sizeof(x) == sizeof(float)) {         \
		volatile float __x;               \
		__x = (x);                        \
	} else if (sizeof(x) == sizeof(double)) { \
		volatile double __x;              \
		__x = (x);                        \
	} else {                                  \
		volatile long double __x;         \
		__x = (x);                        \
	}                                         \
} while(0)

/* Get two 32 bit ints from a double.  */
#define EXTRACT_WORDS(hi,lo,d)                    \
do {                                              \
  union {double f; uint64_t i;} __u;              \
  __u.f = (d);                                    \
  (hi) = __u.i >> 32;                             \
  (lo) = (uint32_t)__u.i;                         \
} while (0)

/* Get the more significant 32 bit int from a double.  */
#define GET_HIGH_WORD(hi,d)                       \
do {                                              \
  union {double f; uint64_t i;} __u;              \
  __u.f = (d);                                    \
  (hi) = __u.i >> 32;                             \
} while (0)

/* Get the less significant 32 bit int from a double.  */
#define GET_LOW_WORD(lo,d)                        \
do {                                              \
  union {double f; uint64_t i;} __u;              \
  __u.f = (d);                                    \
  (lo) = (uint32_t)__u.i;                         \
} while (0)

/* Set a double from two 32 bit ints.  */
#define INSERT_WORDS(d,hi,lo)                     \
do {                                              \
  union {double f; uint64_t i;} __u;              \
  __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo);  \
  (d) = __u.f;                                    \
} while (0)

/* Set the more significant 32 bits of a double from an int.  */
#define SET_HIGH_WORD(d,hi)                       \
do {                                              \
  union {double f; uint64_t i;} __u;              \
  __u.f = (d);                                    \
  __u.i &= 0xffffffff;                            \
  __u.i |= (uint64_t)(hi) << 32;                  \
  (d) = __u.f;                                    \
} while (0)

/* Set the less significant 32 bits of a double from an int.  */
#define SET_LOW_WORD(d,lo)                        \
do {                                              \
  union {double f; uint64_t i;} __u;              \
  __u.f = (d);                                    \
  __u.i &= 0xffffffff00000000ull;                 \
  __u.i |= (uint32_t)(lo);                        \
  (d) = __u.f;                                    \
} while (0)

/* Get a 32 bit int from a float.  */
#define GET_FLOAT_WORD(w,d)                       \
do {                                              \
  union {float f; uint32_t i;} __u;               \
  __u.f = (d);                                    \
  (w) = __u.i;                                    \
} while (0)

/* Set a float from a 32 bit int.  */
#define SET_FLOAT_WORD(d,w)                       \
do {                                              \
  union {float f; uint32_t i;} __u;               \
  __u.i = (w);                                    \
  (d) = __u.f;                                    \
} while (0)

/* fdlibm kernel functions */

int    __rem_pio2_large(double*,double*,int,int,int);

int    __rem_pio2(double,double*);
double __sin(double,double,int);
double __cos(double,double);
double __tan(double,double,int);
double __expo2(double);
double complex __ldexp_cexp(double complex,int);

int    __rem_pio2f(float,double*);
float  __sindf(double);
float  __cosdf(double);
float  __tandf(double,int);
float  __expo2f(float);
float complex __ldexp_cexpf(float complex,int);

int __rem_pio2l(long double, long double *);
long double __sinl(long double, long double, int);
long double __cosl(long double, long double);
long double __tanl(long double, long double, int);

/* polynomial evaluation */
long double __polevll(long double, const long double *, int);
long double __p1evll(long double, const long double *, int);

#endif