From bc45af205cccda131bd316bd0442c2b66b5a690b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 5 Oct 2002 17:13:32 +0000 Subject: [PATCH] Added all former libc/libm files to the libroot/posix directory. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1386 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/libroot/posix/Jamfile | 18 + src/kernel/libroot/posix/dlfcn.c | 36 + src/kernel/libroot/posix/errno.c | 7 + src/kernel/libroot/posix/locale/Jamfile | 7 + src/kernel/libroot/posix/locale/ctype.c | 122 ++ src/kernel/libroot/posix/malloc/Jamfile | 12 + .../libroot/posix/malloc/arch-specific.cpp | 648 +++++++++ .../libroot/posix/malloc/arch-specific.h | 163 +++ src/kernel/libroot/posix/malloc/block.h | 171 +++ src/kernel/libroot/posix/malloc/config.h | 92 ++ src/kernel/libroot/posix/malloc/heap.cpp | 384 ++++++ src/kernel/libroot/posix/malloc/heap.h | 527 ++++++++ src/kernel/libroot/posix/malloc/heapstats.h | 173 +++ .../libroot/posix/malloc/processheap.cpp | 209 +++ src/kernel/libroot/posix/malloc/processheap.h | 267 ++++ .../libroot/posix/malloc/superblock.cpp | 132 ++ src/kernel/libroot/posix/malloc/superblock.h | 287 ++++ .../libroot/posix/malloc/threadheap.cpp | 110 ++ src/kernel/libroot/posix/malloc/threadheap.h | 168 +++ src/kernel/libroot/posix/malloc/wrapper.cpp | 269 ++++ src/kernel/libroot/posix/math/Jamfile | 38 + src/kernel/libroot/posix/math/acosh.c | 98 ++ src/kernel/libroot/posix/math/arch/Jamfile | 3 + .../libroot/posix/math/arch/sh4/Jamfile | 3 + src/kernel/libroot/posix/math/arch/sh4/fabs.S | 10 + .../libroot/posix/math/arch/sh4/frexp.c | 66 + .../libroot/posix/math/arch/sh4/isinf.c | 69 + .../libroot/posix/math/arch/sh4/ldexp.c | 12 + .../libroot/posix/math/arch/x86/Jamfile | 3 + src/kernel/libroot/posix/math/arch/x86/fabs.S | 50 + .../libroot/posix/math/arch/x86/frexp.c | 66 + .../libroot/posix/math/arch/x86/isinf.c | 75 ++ .../libroot/posix/math/arch/x86/ldexp.c | 76 ++ src/kernel/libroot/posix/math/asincos.c | 167 +++ src/kernel/libroot/posix/math/asinh.c | 99 ++ src/kernel/libroot/posix/math/atan.c | 85 ++ src/kernel/libroot/posix/math/atan2.c | 280 ++++ src/kernel/libroot/posix/math/atanh.c | 79 ++ src/kernel/libroot/posix/math/cabs.c | 229 ++++ src/kernel/libroot/posix/math/cbrt.c | 123 ++ src/kernel/libroot/posix/math/cosh.c | 131 ++ src/kernel/libroot/posix/math/erf.c | 408 ++++++ src/kernel/libroot/posix/math/exp.c | 199 +++ src/kernel/libroot/posix/math/exp__E.c | 141 ++ src/kernel/libroot/posix/math/expm1.c | 167 +++ src/kernel/libroot/posix/math/floor.c | 133 ++ src/kernel/libroot/posix/math/fmod.c | 153 +++ src/kernel/libroot/posix/math/gamma.c | 347 +++++ src/kernel/libroot/posix/math/ieee.c | 534 ++++++++ src/kernel/libroot/posix/math/j0.c | 461 +++++++ src/kernel/libroot/posix/math/j1.c | 469 +++++++ src/kernel/libroot/posix/math/jn.c | 318 +++++ src/kernel/libroot/posix/math/lgamma.c | 306 +++++ src/kernel/libroot/posix/math/log.c | 491 +++++++ src/kernel/libroot/posix/math/log10.c | 91 ++ src/kernel/libroot/posix/math/log1p.c | 172 +++ src/kernel/libroot/posix/math/log__L.c | 106 ++ src/kernel/libroot/posix/math/pow.c | 215 +++ src/kernel/libroot/posix/math/sincos.c | 92 ++ src/kernel/libroot/posix/math/sinh.c | 117 ++ src/kernel/libroot/posix/math/tan.c | 74 ++ src/kernel/libroot/posix/math/tanh.c | 100 ++ src/kernel/libroot/posix/rlimit.c | 35 + src/kernel/libroot/posix/stdio/Jamfile | 48 + src/kernel/libroot/posix/stdio/fclose.c | 68 + src/kernel/libroot/posix/stdio/feof.c | 53 + src/kernel/libroot/posix/stdio/fflush.c | 90 ++ src/kernel/libroot/posix/stdio/fgetc.c | 48 + src/kernel/libroot/posix/stdio/fgetln.c | 161 +++ src/kernel/libroot/posix/stdio/fgetpos.c | 52 + src/kernel/libroot/posix/stdio/fgets.c | 105 ++ src/kernel/libroot/posix/stdio/findfp.c | 175 +++ src/kernel/libroot/posix/stdio/flags.c | 91 ++ src/kernel/libroot/posix/stdio/flockfile.c | 17 + src/kernel/libroot/posix/stdio/fopen.c | 88 ++ src/kernel/libroot/posix/stdio/fprintf.c | 61 + src/kernel/libroot/posix/stdio/fputc.c | 55 + src/kernel/libroot/posix/stdio/fputs.c | 61 + src/kernel/libroot/posix/stdio/fread.c | 78 ++ src/kernel/libroot/posix/stdio/fseek.c | 261 ++++ src/kernel/libroot/posix/stdio/fvwrite.c | 211 +++ src/kernel/libroot/posix/stdio/fvwrite.h | 56 + src/kernel/libroot/posix/stdio/fwalk.c | 60 + src/kernel/libroot/posix/stdio/fwrite.c | 68 + src/kernel/libroot/posix/stdio/getc.c | 71 + src/kernel/libroot/posix/stdio/getchar.c | 48 + src/kernel/libroot/posix/stdio/gets.c | 59 + src/kernel/libroot/posix/stdio/getw.c | 46 + src/kernel/libroot/posix/stdio/glue.h | 47 + src/kernel/libroot/posix/stdio/kvsprintf.c | 323 +++++ src/kernel/libroot/posix/stdio/local.h | 85 ++ src/kernel/libroot/posix/stdio/makebuf.c | 121 ++ src/kernel/libroot/posix/stdio/old_stdio.c | 44 + src/kernel/libroot/posix/stdio/printf.c | 65 + src/kernel/libroot/posix/stdio/putc.c | 76 ++ src/kernel/libroot/posix/stdio/putchar.c | 51 + src/kernel/libroot/posix/stdio/puts.c | 60 + src/kernel/libroot/posix/stdio/putw.c | 57 + src/kernel/libroot/posix/stdio/refill.c | 127 ++ src/kernel/libroot/posix/stdio/rewind.c | 51 + src/kernel/libroot/posix/stdio/rget.c | 54 + src/kernel/libroot/posix/stdio/sprintf.c | 73 + src/kernel/libroot/posix/stdio/sscanf.c | 85 ++ src/kernel/libroot/posix/stdio/stdio.c | 104 ++ src/kernel/libroot/posix/stdio/ungetc.c | 146 ++ src/kernel/libroot/posix/stdio/vfprintf.c | 1170 +++++++++++++++++ src/kernel/libroot/posix/stdio/vfscanf.c | 750 +++++++++++ src/kernel/libroot/posix/stdio/vscanf.c | 46 + src/kernel/libroot/posix/stdio/vsprintf.c | 54 + src/kernel/libroot/posix/stdio/wbuf.c | 88 ++ src/kernel/libroot/posix/stdio/wsetup.c | 87 ++ src/kernel/libroot/posix/stdlib/Jamfile | 20 + src/kernel/libroot/posix/stdlib/assert.c | 15 + src/kernel/libroot/posix/stdlib/atoi.c | 86 ++ src/kernel/libroot/posix/stdlib/bsearch.c | 84 ++ src/kernel/libroot/posix/stdlib/env.c | 24 + src/kernel/libroot/posix/stdlib/heapsort.c | 189 +++ src/kernel/libroot/posix/stdlib/merge.c | 361 +++++ src/kernel/libroot/posix/stdlib/multibyte.c | 120 ++ src/kernel/libroot/posix/stdlib/qsort.c | 181 +++ src/kernel/libroot/posix/stdlib/radixsort.c | 318 +++++ src/kernel/libroot/posix/stdlib/rand.c | 105 ++ src/kernel/libroot/posix/stdlib/random.c | 498 +++++++ src/kernel/libroot/posix/stdlib/realpath.c | 160 +++ src/kernel/libroot/posix/stdlib/strtoq.c | 150 +++ src/kernel/libroot/posix/stdlib/strtouq.c | 111 ++ src/kernel/libroot/posix/string/Jamfile | 33 + .../libroot/posix/string/arch/ppc/libc.mk | 24 + .../libroot/posix/string/arch/sh4/libc.mk | 24 + .../libroot/posix/string/arch/x86/memcpy.S | 32 + src/kernel/libroot/posix/string/bcopy.c | 14 + src/kernel/libroot/posix/string/bzero.c | 14 + src/kernel/libroot/posix/string/memchr.c | 24 + src/kernel/libroot/posix/string/memcmp.c | 20 + src/kernel/libroot/posix/string/memcpy.c | 48 + src/kernel/libroot/posix/string/memmove.c | 72 + src/kernel/libroot/posix/string/memset.c | 19 + src/kernel/libroot/posix/string/strcasecmp.c | 71 + src/kernel/libroot/posix/string/strcasestr.c | 64 + src/kernel/libroot/posix/string/strcat.c | 22 + src/kernel/libroot/posix/string/strchr.c | 18 + src/kernel/libroot/posix/string/strcmp.c | 21 + src/kernel/libroot/posix/string/strcpy.c | 19 + src/kernel/libroot/posix/string/strcspn.c | 64 + src/kernel/libroot/posix/string/strdup.c | 52 + src/kernel/libroot/posix/string/strerror.c | 209 +++ src/kernel/libroot/posix/string/strlcat.c | 27 + src/kernel/libroot/posix/string/strlcpy.c | 25 + src/kernel/libroot/posix/string/strlen.c | 20 + src/kernel/libroot/posix/string/strncat.c | 28 + src/kernel/libroot/posix/string/strncmp.c | 22 + src/kernel/libroot/posix/string/strncpy.c | 20 + src/kernel/libroot/posix/string/strnicmp.c | 35 + src/kernel/libroot/posix/string/strnlen.c | 18 + src/kernel/libroot/posix/string/strpbrk.c | 24 + src/kernel/libroot/posix/string/strrchr.c | 24 + src/kernel/libroot/posix/string/strspn.c | 28 + src/kernel/libroot/posix/string/strstr.c | 26 + src/kernel/libroot/posix/string/strtok.c | 32 + src/kernel/libroot/posix/sys/Jamfile | 10 + src/kernel/libroot/posix/sys/chmod.c | 43 + src/kernel/libroot/posix/sys/mkdir.c | 27 + src/kernel/libroot/posix/sys/stat.c | 44 + src/kernel/libroot/posix/sys/sysctl.c | 27 + src/kernel/libroot/posix/unistd/Jamfile | 24 + src/kernel/libroot/posix/unistd/access.c | 27 + src/kernel/libroot/posix/unistd/chown.c | 60 + src/kernel/libroot/posix/unistd/close.c | 20 + src/kernel/libroot/posix/unistd/conf.c | 46 + src/kernel/libroot/posix/unistd/directory.c | 120 ++ src/kernel/libroot/posix/unistd/dup.c | 22 + src/kernel/libroot/posix/unistd/dup2.c | 22 + src/kernel/libroot/posix/unistd/getopt.c | 115 ++ src/kernel/libroot/posix/unistd/ioctl.c | 34 + src/kernel/libroot/posix/unistd/link.c | 54 + src/kernel/libroot/posix/unistd/lseek.c | 14 + src/kernel/libroot/posix/unistd/mount.c | 39 + src/kernel/libroot/posix/unistd/open.c | 48 + src/kernel/libroot/posix/unistd/read.c | 50 + src/kernel/libroot/posix/unistd/sleep.c | 31 + src/kernel/libroot/posix/unistd/truncate.c | 44 + src/kernel/libroot/posix/unistd/usleep.c | 14 + src/kernel/libroot/posix/unistd/write.c | 49 + 183 files changed, 21187 insertions(+) create mode 100644 src/kernel/libroot/posix/Jamfile create mode 100644 src/kernel/libroot/posix/dlfcn.c create mode 100644 src/kernel/libroot/posix/errno.c create mode 100644 src/kernel/libroot/posix/locale/Jamfile create mode 100644 src/kernel/libroot/posix/locale/ctype.c create mode 100644 src/kernel/libroot/posix/malloc/Jamfile create mode 100644 src/kernel/libroot/posix/malloc/arch-specific.cpp create mode 100644 src/kernel/libroot/posix/malloc/arch-specific.h create mode 100644 src/kernel/libroot/posix/malloc/block.h create mode 100644 src/kernel/libroot/posix/malloc/config.h create mode 100644 src/kernel/libroot/posix/malloc/heap.cpp create mode 100644 src/kernel/libroot/posix/malloc/heap.h create mode 100644 src/kernel/libroot/posix/malloc/heapstats.h create mode 100644 src/kernel/libroot/posix/malloc/processheap.cpp create mode 100644 src/kernel/libroot/posix/malloc/processheap.h create mode 100644 src/kernel/libroot/posix/malloc/superblock.cpp create mode 100644 src/kernel/libroot/posix/malloc/superblock.h create mode 100644 src/kernel/libroot/posix/malloc/threadheap.cpp create mode 100644 src/kernel/libroot/posix/malloc/threadheap.h create mode 100644 src/kernel/libroot/posix/malloc/wrapper.cpp create mode 100644 src/kernel/libroot/posix/math/Jamfile create mode 100644 src/kernel/libroot/posix/math/acosh.c create mode 100644 src/kernel/libroot/posix/math/arch/Jamfile create mode 100644 src/kernel/libroot/posix/math/arch/sh4/Jamfile create mode 100644 src/kernel/libroot/posix/math/arch/sh4/fabs.S create mode 100644 src/kernel/libroot/posix/math/arch/sh4/frexp.c create mode 100644 src/kernel/libroot/posix/math/arch/sh4/isinf.c create mode 100644 src/kernel/libroot/posix/math/arch/sh4/ldexp.c create mode 100644 src/kernel/libroot/posix/math/arch/x86/Jamfile create mode 100644 src/kernel/libroot/posix/math/arch/x86/fabs.S create mode 100644 src/kernel/libroot/posix/math/arch/x86/frexp.c create mode 100644 src/kernel/libroot/posix/math/arch/x86/isinf.c create mode 100644 src/kernel/libroot/posix/math/arch/x86/ldexp.c create mode 100644 src/kernel/libroot/posix/math/asincos.c create mode 100644 src/kernel/libroot/posix/math/asinh.c create mode 100644 src/kernel/libroot/posix/math/atan.c create mode 100644 src/kernel/libroot/posix/math/atan2.c create mode 100644 src/kernel/libroot/posix/math/atanh.c create mode 100644 src/kernel/libroot/posix/math/cabs.c create mode 100644 src/kernel/libroot/posix/math/cbrt.c create mode 100644 src/kernel/libroot/posix/math/cosh.c create mode 100644 src/kernel/libroot/posix/math/erf.c create mode 100644 src/kernel/libroot/posix/math/exp.c create mode 100644 src/kernel/libroot/posix/math/exp__E.c create mode 100644 src/kernel/libroot/posix/math/expm1.c create mode 100644 src/kernel/libroot/posix/math/floor.c create mode 100644 src/kernel/libroot/posix/math/fmod.c create mode 100644 src/kernel/libroot/posix/math/gamma.c create mode 100644 src/kernel/libroot/posix/math/ieee.c create mode 100644 src/kernel/libroot/posix/math/j0.c create mode 100644 src/kernel/libroot/posix/math/j1.c create mode 100644 src/kernel/libroot/posix/math/jn.c create mode 100644 src/kernel/libroot/posix/math/lgamma.c create mode 100644 src/kernel/libroot/posix/math/log.c create mode 100644 src/kernel/libroot/posix/math/log10.c create mode 100644 src/kernel/libroot/posix/math/log1p.c create mode 100644 src/kernel/libroot/posix/math/log__L.c create mode 100644 src/kernel/libroot/posix/math/pow.c create mode 100644 src/kernel/libroot/posix/math/sincos.c create mode 100644 src/kernel/libroot/posix/math/sinh.c create mode 100644 src/kernel/libroot/posix/math/tan.c create mode 100644 src/kernel/libroot/posix/math/tanh.c create mode 100644 src/kernel/libroot/posix/rlimit.c create mode 100644 src/kernel/libroot/posix/stdio/Jamfile create mode 100644 src/kernel/libroot/posix/stdio/fclose.c create mode 100644 src/kernel/libroot/posix/stdio/feof.c create mode 100644 src/kernel/libroot/posix/stdio/fflush.c create mode 100644 src/kernel/libroot/posix/stdio/fgetc.c create mode 100644 src/kernel/libroot/posix/stdio/fgetln.c create mode 100644 src/kernel/libroot/posix/stdio/fgetpos.c create mode 100644 src/kernel/libroot/posix/stdio/fgets.c create mode 100644 src/kernel/libroot/posix/stdio/findfp.c create mode 100644 src/kernel/libroot/posix/stdio/flags.c create mode 100644 src/kernel/libroot/posix/stdio/flockfile.c create mode 100644 src/kernel/libroot/posix/stdio/fopen.c create mode 100644 src/kernel/libroot/posix/stdio/fprintf.c create mode 100644 src/kernel/libroot/posix/stdio/fputc.c create mode 100644 src/kernel/libroot/posix/stdio/fputs.c create mode 100644 src/kernel/libroot/posix/stdio/fread.c create mode 100644 src/kernel/libroot/posix/stdio/fseek.c create mode 100644 src/kernel/libroot/posix/stdio/fvwrite.c create mode 100644 src/kernel/libroot/posix/stdio/fvwrite.h create mode 100644 src/kernel/libroot/posix/stdio/fwalk.c create mode 100644 src/kernel/libroot/posix/stdio/fwrite.c create mode 100644 src/kernel/libroot/posix/stdio/getc.c create mode 100644 src/kernel/libroot/posix/stdio/getchar.c create mode 100644 src/kernel/libroot/posix/stdio/gets.c create mode 100644 src/kernel/libroot/posix/stdio/getw.c create mode 100644 src/kernel/libroot/posix/stdio/glue.h create mode 100644 src/kernel/libroot/posix/stdio/kvsprintf.c create mode 100644 src/kernel/libroot/posix/stdio/local.h create mode 100644 src/kernel/libroot/posix/stdio/makebuf.c create mode 100644 src/kernel/libroot/posix/stdio/old_stdio.c create mode 100644 src/kernel/libroot/posix/stdio/printf.c create mode 100644 src/kernel/libroot/posix/stdio/putc.c create mode 100644 src/kernel/libroot/posix/stdio/putchar.c create mode 100644 src/kernel/libroot/posix/stdio/puts.c create mode 100644 src/kernel/libroot/posix/stdio/putw.c create mode 100644 src/kernel/libroot/posix/stdio/refill.c create mode 100644 src/kernel/libroot/posix/stdio/rewind.c create mode 100644 src/kernel/libroot/posix/stdio/rget.c create mode 100644 src/kernel/libroot/posix/stdio/sprintf.c create mode 100644 src/kernel/libroot/posix/stdio/sscanf.c create mode 100644 src/kernel/libroot/posix/stdio/stdio.c create mode 100644 src/kernel/libroot/posix/stdio/ungetc.c create mode 100644 src/kernel/libroot/posix/stdio/vfprintf.c create mode 100644 src/kernel/libroot/posix/stdio/vfscanf.c create mode 100644 src/kernel/libroot/posix/stdio/vscanf.c create mode 100644 src/kernel/libroot/posix/stdio/vsprintf.c create mode 100644 src/kernel/libroot/posix/stdio/wbuf.c create mode 100644 src/kernel/libroot/posix/stdio/wsetup.c create mode 100644 src/kernel/libroot/posix/stdlib/Jamfile create mode 100644 src/kernel/libroot/posix/stdlib/assert.c create mode 100644 src/kernel/libroot/posix/stdlib/atoi.c create mode 100644 src/kernel/libroot/posix/stdlib/bsearch.c create mode 100644 src/kernel/libroot/posix/stdlib/env.c create mode 100644 src/kernel/libroot/posix/stdlib/heapsort.c create mode 100644 src/kernel/libroot/posix/stdlib/merge.c create mode 100644 src/kernel/libroot/posix/stdlib/multibyte.c create mode 100644 src/kernel/libroot/posix/stdlib/qsort.c create mode 100644 src/kernel/libroot/posix/stdlib/radixsort.c create mode 100644 src/kernel/libroot/posix/stdlib/rand.c create mode 100644 src/kernel/libroot/posix/stdlib/random.c create mode 100644 src/kernel/libroot/posix/stdlib/realpath.c create mode 100644 src/kernel/libroot/posix/stdlib/strtoq.c create mode 100644 src/kernel/libroot/posix/stdlib/strtouq.c create mode 100644 src/kernel/libroot/posix/string/Jamfile create mode 100644 src/kernel/libroot/posix/string/arch/ppc/libc.mk create mode 100644 src/kernel/libroot/posix/string/arch/sh4/libc.mk create mode 100644 src/kernel/libroot/posix/string/arch/x86/memcpy.S create mode 100644 src/kernel/libroot/posix/string/bcopy.c create mode 100644 src/kernel/libroot/posix/string/bzero.c create mode 100644 src/kernel/libroot/posix/string/memchr.c create mode 100644 src/kernel/libroot/posix/string/memcmp.c create mode 100644 src/kernel/libroot/posix/string/memcpy.c create mode 100644 src/kernel/libroot/posix/string/memmove.c create mode 100644 src/kernel/libroot/posix/string/memset.c create mode 100644 src/kernel/libroot/posix/string/strcasecmp.c create mode 100644 src/kernel/libroot/posix/string/strcasestr.c create mode 100644 src/kernel/libroot/posix/string/strcat.c create mode 100644 src/kernel/libroot/posix/string/strchr.c create mode 100644 src/kernel/libroot/posix/string/strcmp.c create mode 100644 src/kernel/libroot/posix/string/strcpy.c create mode 100644 src/kernel/libroot/posix/string/strcspn.c create mode 100644 src/kernel/libroot/posix/string/strdup.c create mode 100644 src/kernel/libroot/posix/string/strerror.c create mode 100644 src/kernel/libroot/posix/string/strlcat.c create mode 100644 src/kernel/libroot/posix/string/strlcpy.c create mode 100644 src/kernel/libroot/posix/string/strlen.c create mode 100644 src/kernel/libroot/posix/string/strncat.c create mode 100644 src/kernel/libroot/posix/string/strncmp.c create mode 100644 src/kernel/libroot/posix/string/strncpy.c create mode 100644 src/kernel/libroot/posix/string/strnicmp.c create mode 100644 src/kernel/libroot/posix/string/strnlen.c create mode 100644 src/kernel/libroot/posix/string/strpbrk.c create mode 100644 src/kernel/libroot/posix/string/strrchr.c create mode 100644 src/kernel/libroot/posix/string/strspn.c create mode 100644 src/kernel/libroot/posix/string/strstr.c create mode 100644 src/kernel/libroot/posix/string/strtok.c create mode 100644 src/kernel/libroot/posix/sys/Jamfile create mode 100644 src/kernel/libroot/posix/sys/chmod.c create mode 100644 src/kernel/libroot/posix/sys/mkdir.c create mode 100644 src/kernel/libroot/posix/sys/stat.c create mode 100644 src/kernel/libroot/posix/sys/sysctl.c create mode 100644 src/kernel/libroot/posix/unistd/Jamfile create mode 100644 src/kernel/libroot/posix/unistd/access.c create mode 100644 src/kernel/libroot/posix/unistd/chown.c create mode 100644 src/kernel/libroot/posix/unistd/close.c create mode 100644 src/kernel/libroot/posix/unistd/conf.c create mode 100644 src/kernel/libroot/posix/unistd/directory.c create mode 100644 src/kernel/libroot/posix/unistd/dup.c create mode 100644 src/kernel/libroot/posix/unistd/dup2.c create mode 100644 src/kernel/libroot/posix/unistd/getopt.c create mode 100644 src/kernel/libroot/posix/unistd/ioctl.c create mode 100644 src/kernel/libroot/posix/unistd/link.c create mode 100644 src/kernel/libroot/posix/unistd/lseek.c create mode 100644 src/kernel/libroot/posix/unistd/mount.c create mode 100644 src/kernel/libroot/posix/unistd/open.c create mode 100644 src/kernel/libroot/posix/unistd/read.c create mode 100644 src/kernel/libroot/posix/unistd/sleep.c create mode 100644 src/kernel/libroot/posix/unistd/truncate.c create mode 100644 src/kernel/libroot/posix/unistd/usleep.c create mode 100644 src/kernel/libroot/posix/unistd/write.c diff --git a/src/kernel/libroot/posix/Jamfile b/src/kernel/libroot/posix/Jamfile new file mode 100644 index 0000000000..b8eafd64dc --- /dev/null +++ b/src/kernel/libroot/posix/Jamfile @@ -0,0 +1,18 @@ +SubDir OBOS_TOP src kernel libroot posix ; + +KernelObjects + <$(SOURCE_GRIST)>errno.c + <$(SOURCE_GRIST)>dlfcn.c + <$(SOURCE_GRIST)>rlimit.c + : + -fPIC -DPIC + ; + +SubInclude OBOS_TOP src kernel libroot posix malloc ; +SubInclude OBOS_TOP src kernel libroot posix locale ; +SubInclude OBOS_TOP src kernel libroot posix stdio ; +SubInclude OBOS_TOP src kernel libroot posix string ; +SubInclude OBOS_TOP src kernel libroot posix stdlib ; +SubInclude OBOS_TOP src kernel libroot posix unistd ; +SubInclude OBOS_TOP src kernel libroot posix sys ; +SubInclude OBOS_TOP src kernel libroot posix math ; diff --git a/src/kernel/libroot/posix/dlfcn.c b/src/kernel/libroot/posix/dlfcn.c new file mode 100644 index 0000000000..225e45298e --- /dev/null +++ b/src/kernel/libroot/posix/dlfcn.c @@ -0,0 +1,36 @@ +/* +** Copyright 2002, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include +#include + +void __init__dlfcn(struct uspace_prog_args_t const *); +static struct rld_export_t const *rld; + +void * +dlopen(char const *name, unsigned flags) +{ + return (void*)(rld->dl_open(name, flags)); +} + +void * +dlsym(void *img, char const *name) +{ + return rld->dl_sym((unsigned)img, name, 0); +} + +int +dlclose(void *img) +{ + return rld->dl_close((unsigned)img, 0); +} + + +void +__init__dlfcn(struct uspace_prog_args_t const *uspa) +{ + rld= uspa->rld_export; +} diff --git a/src/kernel/libroot/posix/errno.c b/src/kernel/libroot/posix/errno.c new file mode 100644 index 0000000000..9f3b304f1d --- /dev/null +++ b/src/kernel/libroot/posix/errno.c @@ -0,0 +1,7 @@ +/* errno.c + * + * Simple file to get errno defined!! + */ + +int errno; + diff --git a/src/kernel/libroot/posix/locale/Jamfile b/src/kernel/libroot/posix/locale/Jamfile new file mode 100644 index 0000000000..133b995db6 --- /dev/null +++ b/src/kernel/libroot/posix/locale/Jamfile @@ -0,0 +1,7 @@ +SubDir OBOS_TOP src kernel libroot posix locale ; + +KernelObjects + <$(SOURCE_GRIST)>ctype.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/locale/ctype.c b/src/kernel/libroot/posix/locale/ctype.c new file mode 100644 index 0000000000..23048744fa --- /dev/null +++ b/src/kernel/libroot/posix/locale/ctype.c @@ -0,0 +1,122 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +#define ismask(x) (_ctype[(int)(unsigned char)(x)]) + +static unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + +unsigned char tolower(unsigned char c) +{ + if(isupper(c)) + c -= 'A'-'a'; + return c; +} + +unsigned char toupper(unsigned char c) +{ + if(islower(c)) + c -= 'a'-'A'; + return c; +} + +int isalnum(int c) +{ + return ((ismask(c)&(_U|_L|_D)) != 0); +} + +int isalpha(int c) +{ + return ((ismask(c)&(_U|_L)) != 0); +} + +int iscntrl(int c) +{ + return ((ismask(c)&(_C)) != 0); +} + +int isdigit(int c) +{ + return ((ismask(c)&(_D)) != 0); +} + +int isgraph(int c) +{ + return ((ismask(c)&(_P|_U|_L|_D)) != 0); +} + +int islower(int c) +{ + return ((ismask(c)&(_L)) != 0); +} + +int isprint(int c) +{ + return ((ismask(c)&(_P|_U|_L|_D|_SP)) != 0); +} + +int ispunct(int c) +{ + return ((ismask(c)&(_P)) != 0); +} + +int isspace(int c) +{ + return ((ismask(c)&(_S)) != 0); +} + +int isupper(int c) +{ + return ((ismask(c)&(_U)) != 0); +} + +int isxdigit(int c) +{ + return ((ismask(c)&(_D|_X)) != 0); +} + +int isascii(int c) +{ + return ((unsigned char)c <= 0x7f); +} + +int toascii(int c) +{ + return ((unsigned char)c & 0x7f); +} + diff --git a/src/kernel/libroot/posix/malloc/Jamfile b/src/kernel/libroot/posix/malloc/Jamfile new file mode 100644 index 0000000000..0fb946b77f --- /dev/null +++ b/src/kernel/libroot/posix/malloc/Jamfile @@ -0,0 +1,12 @@ +SubDir OBOS_TOP src kernel libroot posix malloc ; + +KernelObjects + <$(SOURCE_GRIST)>arch-specific.cpp + <$(SOURCE_GRIST)>heap.cpp + <$(SOURCE_GRIST)>processheap.cpp + <$(SOURCE_GRIST)>superblock.cpp + <$(SOURCE_GRIST)>threadheap.cpp + <$(SOURCE_GRIST)>wrapper.cpp + : + -DNEWOS=1 + ; diff --git a/src/kernel/libroot/posix/malloc/arch-specific.cpp b/src/kernel/libroot/posix/malloc/arch-specific.cpp new file mode 100644 index 0000000000..ebf8ba43f1 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/arch-specific.cpp @@ -0,0 +1,648 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +//#include + +#include "arch-specific.h" + +// How many iterations we spin waiting for a lock. +enum { SPIN_LIMIT = 100 }; + +// The values of a user-level lock. +enum { UNLOCKED = 0, LOCKED = 1 }; + +extern "C" { + +#ifdef NEWOS + +#include +#include +#include + +sem_id create_sem(int32 count, const char *name); +status_t delete_sem(sem_id id); +status_t acquire_sem(sem_id id); +status_t release_sem(sem_id id); + +int hoardGetThreadID (void) +{ + return sys_get_current_thread_id(); +} + + +void hoardLockInit (hoardLockType &lock) +{ + lock.ben = 0; + lock.sem = create_sem(1, "a hoard lock"); +} + + +void hoardLock (hoardLockType &lock) +{ + if((atomic_add(&(lock.ben), 1)) >= 1) acquire_sem(lock.sem); +} + + +void hoardUnlock (hoardLockType &lock) +{ + if((atomic_add(&(lock.ben), -1)) > 1) release_sem(lock.sem); +} + +int hoardGetPageSize (void) +{ + return 4096; +} + +int hoardGetNumProcessors (void) +{ + // XXX return the real number of procs here + return 1; +} + +static region_id heap_region = -1; +static addr brk; + +int __heap_init() +{ + // XXX do something better here + if(heap_region < 0) { + heap_region = sys_vm_create_anonymous_region("heap", (void **)&brk, + REGION_ADDR_ANY_ADDRESS, 4*1024*1024, REGION_WIRING_LAZY, LOCK_RW); + } + return 0; +} + +class heap_init_hack_t +{ +public: + heap_init_hack_t(void) { + __heap_init(); + } +} heap_init_hack; + +void * hoardSbrk (long size) +{ + void *ret = (void *)brk; + brk += size; + return ret; +} + +void hoardUnsbrk (void * ptr, long size) +{ + // NOT CURRENTLY IMPLEMENTED! +} + +void hoardYield (void) +{ +} + +#elif defined(WIN32) + +unsigned long hoardInterlockedExchange (unsigned long * oldval, + unsigned long newval) +{ + return InterlockedExchange (reinterpret_cast(oldval), newval); +} + +void hoardCreateThread (hoardThreadType& t, + void *(*function) (void *), + void * arg) +{ + t = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) function, (LPVOID) arg, 0, 0); +} + +void hoardJoinThread (hoardThreadType& t) +{ + WaitForSingleObject (t, INFINITE); +} + +void hoardSetConcurrency (int) +{ +} + +int hoardGetThreadID (void) { + // Threads from Windows 2000 are 4 apart, + // so we shift them over to get an appropriate thread id. + int tid = GetCurrentThreadId() >> 2; + return tid; +} + +void hoardLockInit (hoardLockType& mutex) { + InterlockedExchange (&mutex, 0); +} + +void hoardLock (hoardLockType& mutex) { + // A yielding lock (with an initial spin). + int i; + while (1) { + i = 0; + while (i < SPIN_LIMIT) { + + if (mutex != LOCKED) + if (InterlockedExchange (&mutex, LOCKED) == UNLOCKED) { + // We got the lock. + return; + } + i++; + } + // Yield to other threads. + Sleep (0); + } +} + +void hoardYield (void) { + Sleep (0); +} + +void hoardUnlock (hoardLockType& mutex) { + InterlockedExchange (&mutex, UNLOCKED); +} + +void * hoardSbrk (long size) +{ + + void * ptr = HeapAlloc (GetProcessHeap(), 0, size); + + return (void *) ptr; +} + + +void hoardUnsbrk (void * ptr, long size) +{ + + HeapFree (GetProcessHeap(), 0, ptr); + +} + + +int hoardGetPageSize (void) +{ + SYSTEM_INFO infoReturn[1]; + GetSystemInfo (infoReturn); + return (int) (infoReturn -> dwPageSize); +} + + +int hoardGetNumProcessors (void) +{ + static int numProcessors = 0; + if (numProcessors == 0) { + SYSTEM_INFO infoReturn[1]; + GetSystemInfo (infoReturn); + numProcessors = (int) (infoReturn -> dwNumberOfProcessors); + } + return numProcessors; +} + +#elif defined(__BEOS__) + +#include +#include + +void hoardCreateThread (hoardThreadType &t, + void *( *function)( void *), + void *arg) +{ + t = spawn_thread((int32 (*)(void*))function, "some thread", + B_NORMAL_PRIORITY, arg); + if (t >= B_OK) resume_thread(t); + else debugger("spawn_thread() failed!"); +} + + +void hoardJoinThread (hoardThreadType &t) +{ + status_t dummy; + wait_for_thread(t, &dummy); +} + + +void hoardSetConcurrency (int) +{ +} + + +int hoardGetThreadID (void) +{ + return find_thread(0); +} + + +void hoardLockInit (hoardLockType &lock) +{ + lock.ben = 0; + lock.sem = create_sem(0, "a hoard lock"); +} + + +void hoardLock (hoardLockType &lock) +{ + if((atomic_add(&(lock.ben), 1)) >= 1) acquire_sem(lock.sem); +} + + +void hoardUnlock (hoardLockType &lock) +{ + if((atomic_add(&(lock.ben), -1)) > 1) release_sem(lock.sem); +} + +int hoardGetPageSize (void) +{ + return B_PAGE_SIZE; +} + +int hoardGetNumProcessors (void) +{ + system_info si; + status_t result = get_system_info(&si); + assert (result == B_OK); + return si.cpu_count; +} + + +void * hoardSbrk (long size) +{ + return sbrk(size + hoardHeap::ALIGNMENT - 1); +} + + +void hoardUnsbrk (void * ptr, long size) +{ + // NOT CURRENTLY IMPLEMENTED! +} + +void hoardYield (void) +{ +} + +unsigned long hoardInterlockedExchange (unsigned long * oldval, + unsigned long newval) +{ + // This *should* be made atomic. It's never used in the BeOS + // version, so this is included strictly for completeness. + unsigned long o = *oldval; + *oldval = newval; + return o; +} + + +#else // UNIX + + +#if USE_SPROC +#include +#include +#include +#include +#endif + + +void hoardCreateThread (hoardThreadType& t, + void *(*function) (void *), + void * arg) +{ +#if USE_SPROC + typedef void (*sprocFunction) (void *); + t = sproc ((sprocFunction) function, PR_SADDR, arg); +#else + pthread_attr_t attr; + pthread_attr_init (&attr); +#if defined(_AIX) + // Bound (kernel-level) threads. + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); +#endif + pthread_create (&t, &attr, function, arg); +#endif +} + +void hoardJoinThread (hoardThreadType& t) +{ +#if USE_SPROC + waitpid (t, 0, 0); +#else + pthread_join (t, NULL); +#endif +} + +#if defined(__linux) +// This extern declaration is required for Linux. +extern "C" void pthread_setconcurrency (int n); +#endif + +void hoardSetConcurrency (int n) +{ +#if USE_SPROC + usconfig (CONF_INITUSERS, n); +#elif defined(__SVR4) // Solaris + thr_setconcurrency (n); +#else + pthread_setconcurrency (n); +#endif +} + + +#if defined(__SVR4) // Solaris + +// Solaris's two-level threads model gives us an edge here; +// we can hash on the LWP's id. This helps us in two ways: +// (1) there are likely to be far fewer LWP's than threads, +// (2) if there's a one-to-one correspondence between LWP's +// and the number of processors (usually the case), then +// the number of heaps used will be the same as the number +// of processors (the optimal case). +// Here we rely on an undocumented call in libthread.so, which +// turns out to be MUCH cheaper than the documented _lwp_self(). Go figure. + +extern "C" unsigned int lwp_self(void); +#endif + +int hoardGetThreadID (void) { +#if USE_SPROC + // This hairiness has the same effect as calling getpid(), + // but it's MUCH faster since it avoids making a system call + // and just accesses the sproc-local data directly. + int pid = (int) PRDA->sys_prda.prda_sys.t_pid; + return pid; +#else +#if defined(__linux) + // Consecutive thread id's in Linux are 1024 apart; + // dividing off the 1024 gives us an appropriate thread id. + return (int) pthread_self() >> 10; // (>> 10 = / 1024) +#endif +#if defined(__AIX) + // Consecutive thread id's in AIX are 257 apart; + // dividing off the 257 gives us an appropriate thread id. + return (int) pthread_self() / 257; +#endif +#if defined(__SVR4) + return (int) lwp_self(); +#endif + return (int) pthread_self(); +#endif +} + + +// If we are using either Intel or SPARC, +// we use our own lock implementation +// (spin then yield). This is much cheaper than +// the ordinary mutex, at least on Linux and Solaris. + +#if USER_LOCKS && (defined(i386) || defined(sparc) || defined(__sgi) || defined(ppc)) + +#include + +#if defined(__sgi) +#include +#endif + + +// Atomically: +// retval = *oldval; +// *oldval = newval; +// return retval; + +#if defined(sparc) && !defined(__GNUC__) +extern "C" unsigned long InterlockedExchange (unsigned long * oldval, + unsigned long newval); +#else +unsigned long InterlockedExchange (unsigned long * oldval, + unsigned long newval) +{ +#if defined(sparc) + asm volatile ("swap [%1],%0" + :"=r" (newval) + :"r" (oldval), "0" (newval) + : "memory"); + +#endif +#if defined(i386) + asm volatile ("xchgl %0, %1" + : "=r" (newval) + : "m" (*oldval), "0" (newval) + : "memory"); +#endif +#if defined(__sgi) + newval = test_and_set (oldval, newval); +#endif +#if defined(ppc) + int ret; + asm volatile ("sync;" + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: sync" + : "=&r"(ret) + : "r"(oldval), "r"(newval), "r"(*oldval) + : "cr0", "memory"); +#endif + return newval; +} +#endif + +unsigned long hoardInterlockedExchange (unsigned long * oldval, + unsigned long newval) +{ + return InterlockedExchange (oldval, newval); +} + +void hoardLockInit (hoardLockType& mutex) { + InterlockedExchange (&mutex, UNLOCKED); +} + +#include + +void hoardLock (hoardLockType& mutex) { + // A yielding lock (with an initial spin). + int i; + while (1) { + i = 0; + while (i < SPIN_LIMIT) { + if (InterlockedExchange (&mutex, LOCKED) == UNLOCKED) { + // We got the lock. + return; + } + i++; + } + // The lock is still being held by someone else. + // Give up our quantum. + sched_yield (); + } +} + +void hoardUnlock (hoardLockType& mutex) { + InterlockedExchange (&mutex, UNLOCKED); +} + +#else + +// use non-user-level locks. + +#endif // USER_LOCKS + +void hoardYield (void) +{ + sched_yield (); +} + +#if 1 // !(defined(__sgi)) +#include +#include +#include +#include +#include +#endif + + +void * hoardSbrk (long size) { + // Use mmap for everything but SGI. + // Apparently sproc's and mmap's don't cooperate. +#if 0 // defined(__sgi) + // Protect calls to sbrk() with a lock. +#if USER_LOCKS + static hoardLockType sbrkLock = 0; +#else + static hoardLockType sbrkLock = PTHREAD_MUTEX_INITIALIZER; +#endif + + hoardLock (sbrkLock); + // The "sizeof(double)" should equal hoardHeap::ALIGNMENT. + // This is a workaround (compiler error in g++). + void * moreMemory = sbrk (size + sizeof(double) - 1); + hoardUnlock (sbrkLock); + return moreMemory; +#else + +#if defined(linux) +#if USER_LOCKS + static hoardLockType sbrkLock = 0; +#else + static hoardLockType sbrkLock = PTHREAD_MUTEX_INITIALIZER; +#endif +#endif + // Use mmap to get memory from the backing store. + static int fd = ::open ("/dev/zero", O_RDWR); +#if defined(linux) + hoardLock (sbrkLock); + + // Map starting at this address to maximize the amount of memory + // available to Hoard. Thanks to Jim Nance for this tip. + char * ptr = (char *) mmap ((void *) 0x10000000, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); +#else + char * ptr = (char *) mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); +#endif + + char * retPtr; + if (ptr == (char *) MAP_FAILED) { + retPtr = NULL; + } else { + retPtr = ptr; + } +#if defined(linux) + hoardUnlock (sbrkLock); +#endif + return retPtr; +#endif +} + + +void hoardUnsbrk (void * ptr, long size) +{ +#if defined(linux) +#if USER_LOCKS + static hoardLockType sbrkLock = 0; +#else + static hoardLockType sbrkLock = PTHREAD_MUTEX_INITIALIZER; +#endif +#endif +#if defined(linux) + hoardLock (sbrkLock); +#endif + int result = munmap ((char *) ptr, size); + assert (result == 0); +#if defined(linux) + hoardUnlock (sbrkLock); +#endif +} + + +int hoardGetPageSize (void) +{ + return (int) sysconf(_SC_PAGESIZE); +} + + +#if defined(linux) +#include +#include +#include +#include +#endif + +#if defined(__sgi) +#include +#include +#include +#endif + +int hoardGetNumProcessors (void) +{ +#if !(defined(linux)) +#if defined(__sgi) + static int np = (int) sysmp(MP_NAPROCS); + return np; +#else + static int np = (int) sysconf(_SC_NPROCESSORS_ONLN); + return np; +#endif +#else + static int numProcessors = 0; + + if (numProcessors == 0) { + // Ugly workaround. Linux's sysconf indirectly calls malloc() (at + // least on multiprocessors). So we just read the info from the + // proc file ourselves and count the occurrences of the word + // "processor". + + // We only parse the first 32K of the CPU file. By my estimates, + // that should be more than enough for at least 64 processors. + enum { MAX_PROCFILE_SIZE = 32768 }; + char line[MAX_PROCFILE_SIZE]; + int fd = open ("/proc/cpuinfo", O_RDONLY); + assert (fd); + read(fd, line, MAX_PROCFILE_SIZE); + char * str = line; + while (str) { + str = strstr(str, "processor"); + if (str) { + numProcessors++; + str++; + } + } + close (fd); + assert (numProcessors > 0); + } + return numProcessors; +#endif +} + +#endif // UNIX + +} diff --git a/src/kernel/libroot/posix/malloc/arch-specific.h b/src/kernel/libroot/posix/malloc/arch-specific.h new file mode 100644 index 0000000000..e0340abe42 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/arch-specific.h @@ -0,0 +1,163 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef _ARCH_SPECIFIC_H_ +#define _ARCH_SPECIFIC_H_ + +#include "config.h" + +#if defined(NEWOS) + +#include +#include + +#else + +// Wrap architecture-specific functions. + +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) + +// Windows + +#ifndef WIN32 +#define WIN32 1 +#endif +#include +#include +typedef LONG hoardLockType; +typedef HANDLE hoardThreadType; + +#elif defined(__BEOS__) + +// BeOS + +#include + + +#elif USE_SPROC + +// SGI's SPROC library + +#include +#include + +#else + +// Generic UNIX + +#if defined(__SVR4) // Solaris +#include +#endif + +#include +#include + +#endif +#endif + +#if defined(NEWOS) + +typedef struct { + int32 ben; + sem_id sem; +} hoardLockType; +typedef thread_id hoardThreadType; +inline void * operator new(size_t, void *_P) + {return (_P); } + +#else + +#ifndef WIN32 +#if defined(__BEOS__) +typedef struct { + int32 ben; + sem_id sem; +} hoardLockType; +#elif USER_LOCKS && (defined(i386) || defined(sparc) || defined(__sgi)) +typedef unsigned long hoardLockType; +#else +typedef pthread_mutex_t hoardLockType; +#endif + +#if USE_SPROC +typedef pid_t hoardThreadType; +#elif defined(__BEOS__) +typedef thread_id hoardThreadType; +#else +typedef pthread_t hoardThreadType; +#endif + +#endif +#endif + +extern "C" { + + ///// Thread-related wrappers. + + void hoardCreateThread (hoardThreadType& t, + void *(*function) (void *), + void * arg); + void hoardJoinThread (hoardThreadType& t); + void hoardSetConcurrency (int n); + + // Return a thread identifier appropriate for hashing: + // if the system doesn't produce consecutive thread id's, + // some hackery may be necessary. + int hoardGetThreadID (void); + + ///// Lock-related wrappers. + +#if !defined(WIN32) && !defined(__BEOS__) && !USER_LOCKS + + // Define the lock operations inline to save a little overhead. + + inline void hoardLockInit (hoardLockType& lock) { + pthread_mutex_init (&lock, NULL); + } + + inline void hoardLock (hoardLockType& lock) { + pthread_mutex_lock (&lock); + } + + inline void hoardUnlock (hoardLockType& lock) { + pthread_mutex_unlock (&lock); + } +#else + void hoardLockInit (hoardLockType& lock); + void hoardLock (hoardLockType& lock); + void hoardUnlock (hoardLockType& lock); + +#endif + + ///// Memory-related wrapper. + + int hoardGetPageSize (void); + void * hoardSbrk (long size); + void hoardUnsbrk (void * ptr, long size); + + ///// Other. + + void hoardYield (void); + int hoardGetNumProcessors (void); + unsigned long hoardInterlockedExchange (unsigned long * oldval, + unsigned long newval); +} + +#endif // _ARCH_SPECIFIC_H_ + diff --git a/src/kernel/libroot/posix/malloc/block.h b/src/kernel/libroot/posix/malloc/block.h new file mode 100644 index 0000000000..1c0b0fb7ab --- /dev/null +++ b/src/kernel/libroot/posix/malloc/block.h @@ -0,0 +1,171 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef _BLOCK_H_ +#define _BLOCK_H_ + +#include "config.h" + +//#include + + +class superblock; + +class block { +public: + + block (superblock * sb) + : +#if HEAP_DEBUG + _magic (FREE_BLOCK_MAGIC), +#endif + _next (NULL), + _mySuperblock (sb) + {} + + block& operator= (const block& b) { +#if HEAP_DEBUG + _magic = b._magic; +#endif + _next = b._next; + _mySuperblock = b._mySuperblock; +#if HEAP_FRAG_STATS + _requestedSize = b._requestedSize; +#endif + return *this; + } + + enum { ALLOCATED_BLOCK_MAGIC = 0xcafecafe, + FREE_BLOCK_MAGIC = 0xbabebabe }; + + // Mark this block as free. + inline void markFree (void); + + // Mark this block as allocated. + inline void markAllocated (void); + + // Is this block valid? (i.e., + // does it have the right magic number?) + inline const int isValid (void) const; + + // Return the block's superblock pointer. + inline superblock * getSuperblock (void); + +#if HEAP_FRAG_STATS + void setRequestedSize (size_t s) + { + _requestedSize = s; + } + + size_t getRequestedSize (void) { return _requestedSize; } +#endif + +#if USE_PRIVATE_HEAPS + void setActualSize (size_t s) { _actualSize = s; } + size_t getActualSize (void) { return _actualSize; } +#endif + + void setNext (block * b) { _next = b; } + block * getNext (void) { return _next; } + +private: + +#if USE_PRIVATE_HEAPS + +#if HEAP_DEBUG + union { + unsigned long _magic; + double _d1; // For alignment. + }; +#endif + + block * _next; // The next block in a linked-list of blocks. + size_t _actualSize; // The actual size of the block. + + union { + double _d2; // For alignment. + superblock * _mySuperblock; // A pointer to my superblock. + }; + + +#else // ! USE_PRIVATE_HEAPS + +#if HEAP_DEBUG + union { + unsigned long _magic; + double _d3; // For alignment. + }; +#endif + + block * _next; // The next block in a linked-list of blocks. + superblock * _mySuperblock; // A pointer to my superblock. + +#endif // USE_PRIVATE_HEAPS + +#if HEAP_FRAG_STATS + union { + double _d4; // This is just for alignment purposes. + size_t _requestedSize; // The amount of space requested (vs. allocated). + }; +#endif + + // Disable copying. + + block (const block&); +}; + + +superblock * block::getSuperblock (void) +{ +#if HEAP_DEBUG + assert (isValid()); +#endif + return _mySuperblock; +} + + +void block::markFree (void) +{ +#if HEAP_DEBUG + assert (_magic == ALLOCATED_BLOCK_MAGIC); + _magic = FREE_BLOCK_MAGIC; +#endif +} + + +void block::markAllocated (void) +{ +#if HEAP_DEBUG + assert (_magic == FREE_BLOCK_MAGIC); + _magic = ALLOCATED_BLOCK_MAGIC; +#endif +} + + +const int block::isValid (void) const +{ +#if HEAP_DEBUG + return ((_magic == FREE_BLOCK_MAGIC) + || (_magic == ALLOCATED_BLOCK_MAGIC)); +#else + return 1; +#endif +} + +#endif // _BLOCK_H_ diff --git a/src/kernel/libroot/posix/malloc/config.h b/src/kernel/libroot/posix/malloc/config.h new file mode 100644 index 0000000000..633579b0e8 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/config.h @@ -0,0 +1,92 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#ifndef _REENTRANT +#define _REENTRANT // If defined, generate a multithreaded-capable version. +#endif + +#ifndef USER_LOCKS +#define USER_LOCKS 1 // Use our own user-level locks if they're available for the current architecture. +#endif + +#define HEAP_LOG 0 // If non-zero, keep a log of heap accesses. + + +///// You should not change anything below here. ///// + + +// The base of the exponential used for size classes. +// An object is in size class i if +// base^(b+i-1) * ALIGNMENT < size <= base^(b+i) * ALIGNMENT, +// where b = log_base(ALIGNMENT). +// Note that this puts an upper-limit on internal fragmentation: +// if SIZE_CLASS_BASE is 1.2, then we will never see more than +// 20% internal fragmentation (for aligned requests). + +#define SIZE_CLASS_BASE 1.2 +#define MAX_INTERNAL_FRAGMENTATION 2 + +// The number of groups of superblocks we maintain based on what +// fraction of the superblock is empty. NB: This number must be at +// least 2, and is 1 greater than the EMPTY_FRACTION in heap.h. + +enum { SUPERBLOCK_FULLNESS_GROUP = 9 }; + + + +// DO NOT CHANGE THESE. They require running of maketable to replace +// the values in heap.cpp for the _numBlocks array. + +#define HEAP_DEBUG 0 // If non-zero, keeps extra info for sanity checking. +#define HEAP_STATS 0 // If non-zero, maintain blowup statistics. +#define HEAP_FRAG_STATS 0 // If non-zero, maintain fragmentation statistics. + + +// CACHE_LINE = The number of bytes in a cache line. + +#if defined(i386) || defined(WIN32) +#define CACHE_LINE 32 +#endif + +#ifdef sparc +#define CACHE_LINE 64 +#endif + +#ifdef __sgi +#define CACHE_LINE 128 +#endif + +#ifndef CACHE_LINE +// We don't know what the architecture is, +// so go for the gusto. +#define CACHE_LINE 64 +#endif + +#ifdef __GNUG__ +// Use the max operator, an extension to C++ found in GNU C++. +#define MAX(a,b) ((a) >? (b)) +#else +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + + +#endif // _CONFIG_H_ + diff --git a/src/kernel/libroot/posix/malloc/heap.cpp b/src/kernel/libroot/posix/malloc/heap.cpp new file mode 100644 index 0000000000..d99f8f3f32 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/heap.cpp @@ -0,0 +1,384 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// +#include "config.h" + +#include "heap.h" +#define NEED_LG +#include "processheap.h" +#include "superblock.h" + +static const char version[] = "The Hoard memory allocator, version 2.0 (http://www.hoard.org). Copyright (C) 1998, 1999, 2000 The University of Texas at Austin. $Id: heap.cpp,v 1.1 2002/10/05 17:13:30 axeld Exp $"; + +// NB: Use maketable.cpp to update this +// if SIZE_CLASSES, ALIGNMENT, SIZE_CLASS_BASE, MAX_EMPTY_SUPERBLOCKS, +// or SUPERBLOCK_SIZE changes. + +#if (MAX_INTERNAL_FRAGMENTATION == 2) + +size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = {8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 72UL, 80UL, 96UL, 120UL, 144UL, 168UL, 200UL, 240UL, 288UL, 344UL, 416UL, 496UL, 592UL, 712UL, 856UL, 1024UL, 1232UL, 1472UL, 1768UL, 2120UL, 2544UL, 3048UL, 3664UL, 4392UL, 5272UL, 6320UL, 7584UL, 9104UL, 10928UL, 13112UL, 15728UL, 18872UL, 22648UL, 27176UL, 32616UL, 39136UL, 46960UL, 56352UL, 67624UL, 81144UL, 97376UL, 116848UL, 140216UL, 168256UL, 201904UL, 242288UL, 290744UL, 348896UL, 418672UL, 502408UL, 602888UL, 723464UL, 868152UL, 1041784UL, 1250136UL, 1500160UL, 1800192UL, 2160232UL, 2592280UL, 3110736UL, 3732880UL, 4479456UL, 5375344UL, 6450408UL, 7740496UL, 9288592UL, 11146312UL, 13375568UL, 16050680UL, 19260816UL, 23112984UL, 27735576UL, 33282688UL, 39939224UL, 47927072UL, 57512488UL, 69014984UL, 82817976UL, 99381576UL, 119257888UL, 143109472UL, 171731360UL, 206077632UL, 247293152UL, 296751776UL, 356102144UL, 427322560UL, 512787072UL, 615344512UL, 738413376UL, 886096064UL, 1063315264UL}; + +size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {4096UL, 2048UL, 1364UL, 1024UL, 816UL, 680UL, 584UL, 452UL, 408UL, 340UL, 272UL, 224UL, 192UL, 160UL, 136UL, 112UL, 92UL, 76UL, 64UL, 52UL, 44UL, 36UL, 32UL, 24UL, 20UL, 16UL, 12UL, 12UL, 8UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL}; + +#elif (MAX_INTERNAL_FRAGMENTATION == 6) + +size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = {8UL, 16UL, 24UL, 32UL, 48UL, 72UL, 112UL, 176UL, 288UL, 456UL, 728UL, 1160UL, 1848UL, 2952UL, 4728UL, 7560UL, 12096UL, 19344UL, 30952UL, 49520UL, 79232UL, 126768UL, 202832UL, 324520UL, 519232UL, 830768UL, 1329232UL, 2126768UL, 3402824UL, 5444520UL, 8711232UL, 13937968UL, 22300752UL, 35681200UL, 57089912UL, 91343856UL, 146150176UL, 233840256UL, 374144416UL, 598631040UL, 957809728UL, 1532495488UL}; + +size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {4096UL, 2048UL, 1364UL, 1024UL, 680UL, 452UL, 292UL, 184UL, 112UL, 68UL, 44UL, 28UL, 16UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL}; + +#elif (MAX_INTERNAL_FRAGMENTATION == 10) + +size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES] = {8UL, 16UL, 32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL, 8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL, 1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL, 67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL, 2147483648UL}; + +size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {4096UL, 2048UL, 1024UL, 512UL, 256UL, 128UL, 64UL, 32UL, 16UL, 8UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL}; + +#else +#error "Undefined size class base." +#endif + + +hoardHeap::hoardHeap (void) + : _index (0), + _reusableSuperblocks (NULL), + _reusableSuperblocksCount (0) +#if HEAP_DEBUG + , _magic (HEAP_MAGIC) +#endif +{ + // Initialize the per-heap lock. + hoardLockInit (_lock); + for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { + for (int j = 0; j < SIZE_CLASSES; j++) { + // Initialize all superblocks lists to empty. + _superblocks[i][j] = NULL; + } + } + for (int k = 0; k < SIZE_CLASSES; k++) { + _leastEmptyBin[k] = 0; + } +} + + +void hoardHeap::insertSuperblock (int sizeclass, + superblock * sb, + processHeap * pHeap) +{ + assert (sb->isValid()); + assert (sb->getBlockSizeClass() == sizeclass); + assert (sb->getPrev() == NULL); + assert (sb->getNext() == NULL); + assert (_magic == HEAP_MAGIC); + + // Now it's ours. + sb->setOwner (this); + + // How full is this superblock? We'll use this information to put + // it into the right 'bin'. + sb->computeFullness(); + int fullness = sb->getFullness(); + + // Update the stats. + incStats (sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + + if ((fullness == 0) && + (sb->getNumBlocks() > 1) && + (sb->getNumBlocks() == sb->getNumAvailable())) { + // Recycle this superblock. +#if 0 + removeSuperblock (sb, sizeclass); + // Update the stats. + decStats (sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + // Free it immediately. + const size_t s = sizeFromClass (sizeclass); + const int blksize = align (sizeof(block) + s); +#if HEAP_LOG + // Record the memory deallocation. + MemoryRequest m; + m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); + pHeap->getLog(getIndex()).append(m); +#endif +#if HEAP_FRAG_STATS + pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); +#endif + hoardUnsbrk (sb, align (sizeof(superblock) + blksize)); +#else + recycle (sb); +#endif + } else { + + // Insert it into the appropriate list. + superblock *& head = _superblocks[fullness][sizeclass]; + sb->insertBefore (head); + head = sb; + assert (head->isValid()); + + // Reset the least-empty bin counter. + _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN; + } +} + + +superblock * hoardHeap::removeMaxSuperblock (int sizeclass) +{ + assert (_magic == HEAP_MAGIC); + + superblock * head = NULL; + + // First check the reusable superblocks list. + + head = reuse (sizeclass); + if (head) { + // We found one. Since we're removing this superblock, update the + // stats accordingly. + decStats (sizeclass, + head->getNumBlocks() - head->getNumAvailable(), + head->getNumBlocks()); + + return head; + } + + // Instead of finding the superblock with the most available space + // (something that would either involve a linear scan through the + // superblocks or maintaining the superblocks in sorted order), we + // just pick one that is no more than + // 1/(SUPERBLOCK_FULLNESS_GROUP-1) more full than the superblock + // with the most available space. We start with the emptiest group. + + int i = 0; + + // Note: the last group (SUPERBLOCK_FULLNESS_GROUP - 1) is full, so + // we never need to check it. But for robustness, we leave it in. + while (i < SUPERBLOCK_FULLNESS_GROUP) { + head = _superblocks[i][sizeclass]; + if (head) { + break; + } + i++; + } + + if (!head) { + return NULL; + } + + // Make sure that this superblock is at least 1/EMPTY_FRACTION + // empty. + assert (head->getNumAvailable() * EMPTY_FRACTION >= head->getNumBlocks()); + + removeSuperblock (head, sizeclass); + + assert (head->isValid()); + assert (head->getPrev() == NULL); + assert (head->getNext() == NULL); + return head; +} + + +void hoardHeap::removeSuperblock (superblock * sb, + int sizeclass) +{ + assert (_magic == HEAP_MAGIC); + + assert (sb->isValid()); + assert (sb->getOwner() == this); + assert (sb->getBlockSizeClass() == sizeclass); + + for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) { + if (sb == _superblocks[i][sizeclass]) { + _superblocks[i][sizeclass] = sb->getNext(); + if (_superblocks[i][sizeclass] != NULL) { + assert (_superblocks[i][sizeclass]->isValid()); + } + break; + } + } + + sb->remove(); + decStats (sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks()); +} + + +void hoardHeap::moveSuperblock (superblock * sb, + int sizeclass, + int fromBin, + int toBin) +{ + assert (_magic == HEAP_MAGIC); + assert (sb->isValid()); + assert (sb->getOwner() == this); + assert (sb->getBlockSizeClass() == sizeclass); + assert (sb->getFullness() == toBin); + + // Remove the superblock from the old bin. + + superblock *& oldHead = _superblocks[fromBin][sizeclass]; + if (sb == oldHead) { + oldHead = sb->getNext(); + if (oldHead != NULL) { + assert (oldHead->isValid()); + } + } + + sb->remove(); + + // Insert the superblock into the new bin. + + superblock *& newHead = _superblocks[toBin][sizeclass]; + sb->insertBefore (newHead); + newHead = sb; + assert (newHead->isValid()); + + // Reset the least-empty bin counter. + _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN; +} + + +// The heap lock must be held when this procedure is called. + +int hoardHeap::freeBlock (block *& b, + superblock *& sb, + int sizeclass, + processHeap * pHeap) +{ + assert (sb->isValid()); + assert (b->isValid()); + assert (this == sb->getOwner()); + + const int oldFullness = sb->getFullness(); + sb->putBlock (b); + decUStats (sizeclass); + const int newFullness = sb->getFullness(); + + // Free big superblocks. + if (sb->getNumBlocks() == 1) { + removeSuperblock (sb, sizeclass); + const size_t s = sizeFromClass (sizeclass); + const int blksize = align (sizeof(block) + s); +#if HEAP_LOG + // Record the memory deallocation. + MemoryRequest m; + m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); + pHeap->getLog(getIndex()).append(m); +#endif +#if HEAP_FRAG_STATS + pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); +#endif + hoardUnsbrk (sb, align (sizeof(superblock) + blksize)); + return 1; + } + + // If the fullness value has changed, move the superblock. + if (newFullness != oldFullness) { + moveSuperblock (sb, sizeclass, oldFullness, newFullness); + } else { + // Move the superblock to the front of its list (to reduce + // paging). + superblock *& head = _superblocks[newFullness][sizeclass]; + if (sb != head) { + sb->remove(); + sb->insertBefore (head); + head = sb; + } + } + + // If the superblock is now empty, recycle it. + + if ((newFullness == 0) && + (sb->getNumBlocks() == sb->getNumAvailable())) { + removeSuperblock (sb, sizeclass); +#if 0 + // Free it immediately. + const size_t s = sizeFromClass (sizeclass); + const int blksize = align (sizeof(block) + s); +#if HEAP_LOG + // Record the memory deallocation. + MemoryRequest m; + m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); + pHeap->getLog(getIndex()).append(m); +#endif +#if HEAP_FRAG_STATS + pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); +#endif + hoardUnsbrk (sb, align (sizeof(superblock) + blksize)); + return 1; +#else + recycle (sb); + // Update the stats. This restores the stats to their state + // before the call to removeSuperblock, above. + incStats (sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); +#endif + } + + // If this is the process heap, then we're done. + if (this == (hoardHeap *) pHeap) { + return 0; + } + + // + // Release a superblock, if necessary. + // + + // + // Check to see if the amount free exceeds the release threshold + // (two superblocks worth of blocks for a given sizeclass) and if + // the heap is sufficiently empty. + // + + // We never move anything to the process heap if we're on a + // uniprocessor. + if (_numProcessors > 1) { + int inUse, allocated; + getStats (sizeclass, inUse, allocated); + if ((inUse < allocated - getReleaseThreshold(sizeclass)) + && (EMPTY_FRACTION * inUse < EMPTY_FRACTION * allocated - allocated)) { + + // We've crossed the magical threshold. Find the superblock with + // the most free blocks and give it to the process heap. + superblock * const maxSb = removeMaxSuperblock (sizeclass); + assert (maxSb != NULL); + + // Update the statistics. + + assert (maxSb->getNumBlocks() >= maxSb->getNumAvailable()); + + // Give the superblock back to the process heap. + pHeap->release (maxSb); + + } + } + + return 0; +} + +// Static initialization of the number of processors (and a mask). + +int hoardHeap::_numProcessors; +int hoardHeap::_numProcessorsMask; + +hoardHeap::_initNumProcs::_initNumProcs(void) +{ + hoardHeap::_numProcessors = hoardGetNumProcessors(); + hoardHeap::_numProcessorsMask = (1 << (lg(hoardGetNumProcessors()) + 1)) - 1; +} + +static hoardHeap::_initNumProcs initProcs; diff --git a/src/kernel/libroot/posix/malloc/heap.h b/src/kernel/libroot/posix/malloc/heap.h new file mode 100644 index 0000000000..5d43fa0b15 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/heap.h @@ -0,0 +1,527 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +/* + heap.h + ------------------------------------------------------------------------ + hoardHeap, the base class for threadHeap and processHeap. + ------------------------------------------------------------------------ + @(#) $Id: heap.h,v 1.1 2002/10/05 17:13:30 axeld Exp $ + ------------------------------------------------------------------------ + Emery Berger | + Department of Computer Sciences | + University of Texas at Austin | + ======================================================================== +*/ + + +#ifndef _HEAP_H_ +#define _HEAP_H_ + +#include "config.h" + +//include +//#include + +#include "arch-specific.h" +#include "superblock.h" +#include "heapstats.h" + +class processHeap; // forward declaration + + +class hoardHeap { + +public: + + hoardHeap (void); + + // A superblock that holds more than one object must hold at least + // this many bytes. + enum { SUPERBLOCK_SIZE = 8192 }; + + // A thread heap must be at least 1/EMPTY_FRACTION empty before we + // start returning superblocks to the process heap. + enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 }; + + // Reset value for the least-empty bin. The last bin + // (SUPERBLOCK_FULLNESS_GROUP-1) is for completely full superblocks, + // so we use the next-to-last bin. + enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 }; + + // The number of empty superblocks that we allow any thread heap to + // hold once the thread heap has fallen below 1/EMPTY_FRACTION + // empty. + enum { MAX_EMPTY_SUPERBLOCKS = EMPTY_FRACTION }; + + // The maximum number of thread heaps we allow. (NOT the maximum + // number of threads -- Hoard imposes no such limit.) This must be + // a power of two! NB: This number is twice the maximum number of + // PROCESSORS supported by Hoard. + enum { MAX_HEAPS = 128 }; + + // ANDing with this rounds to MAX_HEAPS. + enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 }; + + // + // The number of size classes. This combined with the + // SIZE_CLASS_BASE determine the maximum size of an object. + // + // NB: Once this is changed, you must execute maketable.cpp and put + // the generated values into heap.cpp. + +#if MAX_INTERNAL_FRAGMENTATION == 2 + enum { SIZE_CLASSES = 115 }; +#elif MAX_INTERNAL_FRAGMENTATION == 6 + enum { SIZE_CLASSES = 46 }; +#elif MAX_INTERNAL_FRAGMENTATION == 10 + enum { SIZE_CLASSES = 32 }; +#else +#error "Undefined size class base." +#endif + + // Every object is aligned so that it can always hold a double. + enum { ALIGNMENT = sizeof(double) }; + + // ANDing with this rounds to ALIGNMENT. + enum { ALIGNMENT_MASK = ALIGNMENT - 1}; + + // Used for sanity checking. + enum { HEAP_MAGIC = 0x0badcafe }; + + // Get the usage and allocated statistics. + inline void getStats (int sizeclass, int& U, int& A); + + +#if HEAP_STATS + // How much is the maximum ever in use for this size class? + inline int maxInUse (int sizeclass); + + // How much is the maximum memory allocated for this size class? + inline int maxAllocated (int sizeclass); +#endif + + // Insert a superblock into our list. + void insertSuperblock (int sizeclass, + superblock * sb, + processHeap * pHeap); + + // Remove the superblock with the most free space. + superblock * removeMaxSuperblock (int sizeclass); + + // Find an available superblock (i.e., with some space in it). + inline superblock * findAvailableSuperblock (int sizeclass, + block *& b, + processHeap * pHeap); + + // Lock this heap. + inline void lock (void); + + // Unlock this heap. + inline void unlock (void); + + // Set our index number (which heap we are). + inline void setIndex (int i); + + // Get our index number (which heap we are). + inline int getIndex (void); + + // Free a block into a superblock. + // This is used by processHeap::free(). + // Returns 1 iff the superblock was munmapped. + int freeBlock (block *& b, + superblock *& sb, + int sizeclass, + processHeap * pHeap); + + //// Utility functions //// + + // Return the size class for a given size. + inline static int sizeClass (const size_t sz); + + // Return the size corresponding to a given size class. + inline static size_t sizeFromClass (const int sizeclass); + + // Return the release threshold corresponding to a given size class. + inline static int getReleaseThreshold (const int sizeclass); + + // Return how many blocks of a given size class fit into a superblock. + inline static int numBlocks (const int sizeclass); + + // Align a value. + inline static size_t align (const size_t sz); + +private: + + // Disable copying and assignment. + + hoardHeap (const hoardHeap&); + const hoardHeap& operator= (const hoardHeap&); + + // Recycle a superblock. + inline void recycle (superblock *); + + // Reuse a superblock (if one is available). + inline superblock * reuse (int sizeclass); + + // Remove a particular superblock. + void removeSuperblock (superblock *, int sizeclass); + + // Move a particular superblock from one bin to another. + void moveSuperblock (superblock *, + int sizeclass, + int fromBin, + int toBin); + + // Update memory in-use and allocated statistics. + // (*UStats = just update U.) + inline void incStats (int sizeclass, int updateU, int updateA); + inline void incUStats (int sizeclass); + + inline void decStats (int sizeclass, int updateU, int updateA); + inline void decUStats (int sizeclass); + + //// Members //// + +#if HEAP_DEBUG + // For sanity checking. + const unsigned long _magic; +#else + #define _magic HEAP_MAGIC +#endif + + // Heap statistics. + heapStats _stats[SIZE_CLASSES]; + + // The per-heap lock. + hoardLockType _lock; + + // Which heap this is (0 = the process (global) heap). + int _index; + + // Reusable superblocks. + superblock * _reusableSuperblocks; + int _reusableSuperblocksCount; + + // Lists of superblocks. + superblock * _superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES]; + + // The current least-empty superblock bin. + int _leastEmptyBin[SIZE_CLASSES]; + + // The lookup table for size classes. + static size_t _sizeTable[SIZE_CLASSES]; + + // The lookup table for release thresholds. + static size_t _threshold[SIZE_CLASSES]; + +public: + // A little helper class that we use to define some statics. + class _initNumProcs { + public: + _initNumProcs(void); + }; + + friend class _initNumProcs; +protected: + // number of CPUs, cached + static int _numProcessors; + static int _numProcessorsMask; +}; + + + +void hoardHeap::incStats (int sizeclass, int updateU, int updateA) { + assert (_magic == HEAP_MAGIC); + assert (updateU >= 0); + assert (updateA >= 0); + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + _stats[sizeclass].incStats (updateU, updateA); +} + + + +void hoardHeap::incUStats (int sizeclass) { + assert (_magic == HEAP_MAGIC); + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + _stats[sizeclass].incUStats (); +} + + +void hoardHeap::decStats (int sizeclass, int updateU, int updateA) { + assert (_magic == HEAP_MAGIC); + assert (updateU >= 0); + assert (updateA >= 0); + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + _stats[sizeclass].decStats (updateU, updateA); +} + + +void hoardHeap::decUStats (int sizeclass) +{ + assert (_magic == HEAP_MAGIC); + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + _stats[sizeclass].decUStats(); +} + + +void hoardHeap::getStats (int sizeclass, int& U, int& A) { + assert (_magic == HEAP_MAGIC); + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + _stats[sizeclass].getStats (U, A); +} + + +#if HEAP_STATS +int hoardHeap::maxInUse (int sizeclass) { + assert (_magic == HEAP_MAGIC); + return _stats[sizeclass].getUmax(); +} + + +int hoardHeap::maxAllocated (int sizeclass) { + assert (_magic == HEAP_MAGIC); + return _stats[sizeclass].getAmax(); +} +#endif + + +superblock * hoardHeap::findAvailableSuperblock (int sizeclass, + block *& b, + processHeap * pHeap) +{ + assert (this); + assert (_magic == HEAP_MAGIC); + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + + superblock * sb = NULL; + int reUsed = 0; + + // Look through the superblocks, starting with the almost-full ones + // and going to the emptiest ones. The Least Empty Bin for a + // sizeclass is a conservative approximation (fixed after one + // iteration) of the first bin that has superblocks in it, starting + // with (surprise) the least-empty bin. + + for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) { + sb = _superblocks[i][sizeclass]; + if (sb == NULL) { + if (i == _leastEmptyBin[sizeclass]) { + // There wasn't a superblock in this bin, + // so we adjust the least empty bin. + _leastEmptyBin[sizeclass]--; + } + } else if(sb->getNumAvailable() > 0){ + assert (sb->getOwner() == this); + break; + } + sb = NULL; + } + +#if 1 + if (sb == NULL) { + // Try to reuse a superblock. + sb = reuse (sizeclass); + if (sb) { + assert (sb->getOwner() == this); + reUsed = 1; + } + } +#endif + + if (sb != NULL) { + // Sanity checks: + // This superblock is 'valid'. + assert (sb->isValid()); + // This superblock has the right ownership. + assert (sb->getOwner() == this); + + int oldFullness = sb->getFullness(); + + // Now get a block from the superblock. + // This superblock must have space available. + b = sb->getBlock(); + assert (b != NULL); + + // Update the stats. + incUStats (sizeclass); + + if (reUsed) { + insertSuperblock (sizeclass, sb, pHeap); + // Fix the stats (since insert will just have incremented them + // by this amount). + decStats (sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + } else { + // If we've crossed a fullness group, + // move the superblock. + int fullness = sb->getFullness(); + + if (fullness != oldFullness) { + // Move the superblock. + moveSuperblock (sb, sizeclass, oldFullness, fullness); + } + } + } + + // Either we didn't find a superblock or we did and got a block. + assert ((sb == NULL) || (b != NULL)); + // Either we didn't get a block or we did and we also got a superblock. + assert ((b == NULL) || (sb != NULL)); + + return sb; +} + + +int hoardHeap::sizeClass (const size_t sz) { + // Find the size class for a given object size + // (the smallest i such that _sizeTable[i] >= sz). + int sizeclass = 0; + while (_sizeTable[sizeclass] < sz) + { + sizeclass++; + assert (sizeclass < SIZE_CLASSES); + } + return sizeclass; +} + + +size_t hoardHeap::sizeFromClass (const int sizeclass) { + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + return _sizeTable[sizeclass]; +} + + +int hoardHeap::getReleaseThreshold (const int sizeclass) { + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + return _threshold[sizeclass]; +} + + +int hoardHeap::numBlocks (const int sizeclass) { + assert (sizeclass >= 0); + assert (sizeclass < SIZE_CLASSES); + const size_t s = sizeFromClass (sizeclass); + assert (s > 0); + const int blksize = align (sizeof(block) + s); + // Compute the number of blocks that will go into this superblock. + int nb = MAX (1, ((SUPERBLOCK_SIZE - sizeof(superblock)) / blksize)); + return nb; +} + + +void hoardHeap::lock (void) +{ + assert (_magic == HEAP_MAGIC); + hoardLock (_lock); +} + + +void hoardHeap::unlock (void) { + assert (_magic == HEAP_MAGIC); + hoardUnlock (_lock); +} + + +size_t hoardHeap::align (const size_t sz) +{ + // Align sz up to the nearest multiple of ALIGNMENT. + // This is much faster than using multiplication + // and division. + return (sz + ALIGNMENT_MASK) & ~ALIGNMENT_MASK; +} + + +void hoardHeap::setIndex (int i) +{ + _index = i; +} + + +int hoardHeap::getIndex (void) +{ + return _index; +} + + + + +void hoardHeap::recycle (superblock * sb) +{ + assert (sb != NULL); + assert (sb->getOwner() == this); + assert (sb->getNumBlocks() > 1); + assert (sb->getNext() == NULL); + assert (sb->getPrev() == NULL); + assert (hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1); + sb->insertBefore (_reusableSuperblocks); + _reusableSuperblocks = sb; + ++_reusableSuperblocksCount; + // printf ("count: %d => %d\n", getIndex(), _reusableSuperblocksCount); +} + + +superblock * hoardHeap::reuse (int sizeclass) +{ + if (_reusableSuperblocks == NULL) { + return NULL; + } + + // Make sure that we aren't using a sizeclass + // that is too big for a 'normal' superblock. + if (hoardHeap::numBlocks(sizeclass) <= 1) { + return NULL; + } + + // Pop off a superblock from the reusable-superblock list. + assert (_reusableSuperblocksCount > 0); + superblock * sb = _reusableSuperblocks; + _reusableSuperblocks = sb->getNext(); + sb->remove(); + assert (sb->getNumBlocks() > 1); + --_reusableSuperblocksCount; + + // Reformat the superblock if necessary. + if (sb->getBlockSizeClass() != sizeclass) { + decStats (sb->getBlockSizeClass(), + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + + sb = new ((char *) sb) superblock (numBlocks(sizeclass), sizeclass, this); + + incStats (sizeclass, + sb->getNumBlocks() - sb->getNumAvailable(), + sb->getNumBlocks()); + } + + assert (sb->getOwner() == this); + assert (sb->getBlockSizeClass() == sizeclass); + return sb; +} + +#endif // _HEAP_H_ diff --git a/src/kernel/libroot/posix/malloc/heapstats.h b/src/kernel/libroot/posix/malloc/heapstats.h new file mode 100644 index 0000000000..fceefec27b --- /dev/null +++ b/src/kernel/libroot/posix/malloc/heapstats.h @@ -0,0 +1,173 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef _HEAPSTATS_H_ +#define _HEAPSTATS_H_ + +#include "config.h" + +//#include +//#include + + +class heapStats { +public: + + heapStats (void) + : + U (0), + A (0) +#if HEAP_STATS + ,Umax (0), + Amax (0) +#endif + {} + + inline const heapStats& operator= (const heapStats& p); + + inline void incStats (int updateU, int updateA); + inline void incUStats (void); + + inline void decStats (int updateU, int updateA); + inline void decUStats (void); + inline void decUStats (int& Uout, int& Aout); + + inline void getStats (int& Uout, int& Aout); + + +#if HEAP_STATS + + inline int getUmax (void); + inline int getAmax (void); + +#endif + + +private: + + // U and A *must* be the first items in this class -- + // we will depend on this to atomically update them. + + int U; // Memory in use. + int A; // Memory allocated. + +#if HEAP_STATS + int Umax; + int Amax; +#endif +}; + + +inline void heapStats::incStats (int updateU, int updateA) +{ + assert (updateU >= 0); + assert (updateA >= 0); + assert (U <= A); + assert (U >= 0); + assert (A >= 0); + U += updateU; + A += updateA; +#if HEAP_STATS + Amax = MAX (Amax, A); + Umax = MAX (Umax, U); +#endif + assert (U <= A); + assert (U >= 0); + assert (A >= 0); +} + + +inline void heapStats::incUStats (void) +{ + assert (U < A); + assert (U >= 0); + assert (A >= 0); + U++; +#if HEAP_STATS + Umax = MAX (Umax, U); +#endif + assert (U >= 0); + assert (A >= 0); +} + + +inline void heapStats::decStats (int updateU, int updateA) +{ + assert (updateU >= 0); + assert (updateA >= 0); + assert (U <= A); + assert (U >= updateU); + assert (A >= updateA); + U -= updateU; + A -= updateA; + assert (U <= A); + assert (U >= 0); + assert (A >= 0); +} + + +inline void heapStats::decUStats (int& Uout, int& Aout) +{ + assert (U <= A); + assert (U > 0); + assert (A >= 0); + U--; + Uout = U; + Aout = A; + assert (U >= 0); + assert (A >= 0); +} + + +inline void heapStats::decUStats (void) +{ + assert (U <= A); + assert (U > 0); + assert (A >= 0); + U--; +} + + +inline void heapStats::getStats (int& Uout, int& Aout) +{ + assert (U >= 0); + assert (A >= 0); + Uout = U; + Aout = A; + assert (U <= A); + assert (U >= 0); + assert (A >= 0); +} + + +#if HEAP_STATS +inline int heapStats::getUmax (void) +{ + return Umax; +} + + +inline int heapStats::getAmax (void) +{ + return Amax; +} +#endif // HEAP_STATS + + + +#endif // _HEAPSTATS_H_ diff --git a/src/kernel/libroot/posix/malloc/processheap.cpp b/src/kernel/libroot/posix/malloc/processheap.cpp new file mode 100644 index 0000000000..61ee8224aa --- /dev/null +++ b/src/kernel/libroot/posix/malloc/processheap.cpp @@ -0,0 +1,209 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "config.h" + +#if USE_PRIVATE_HEAPS +#include "privateheap.h" +#define HEAPTYPE privateHeap +#else +#define HEAPTYPE threadHeap +#include "threadheap.h" +#endif + +#include "processheap.h" + + +processHeap::processHeap (void) + : _buffer (NULL), + _bufferCount (0) +#if HEAP_FRAG_STATS + , _currentAllocated (0), + _currentRequested (0), + _maxAllocated (0), + _inUseAtMaxAllocated (0), + _maxRequested (0) +#endif +{ + int i; + // The process heap is heap 0. + setIndex (0); + for (i = 0; i < MAX_HEAPS; i++) { + // Set every thread's process heap to this one. + theap[i].setpHeap (this); + // Set every thread heap's index. + theap[i].setIndex (i + 1); + } +#if HEAP_LOG + for (i = 0; i < MAX_HEAPS + 1; i++) { + char fname[255]; + sprintf (fname, "log%d", i); + unlink (fname); + _log[i].open (fname); + } +#endif +#if HEAP_FRAG_STATS + hoardLockInit (_statsLock); +#endif + hoardLockInit (_bufferLock); +} + + +// Print out statistics information. +void processHeap::stats (void) { +#if HEAP_STATS + int umax = 0; + int amax = 0; + for (int j = 0; j < MAX_HEAPS; j++) { + for (int i = 0; i < SIZE_CLASSES; i++) { + amax += theap[j].maxAllocated(i) * sizeFromClass (i); + umax += theap[j].maxInUse(i) * sizeFromClass (i); + } + } + printf ("Amax <= %d, Umax <= %d\n", amax, umax); +#if HEAP_FRAG_STATS + amax = getMaxAllocated(); + umax = getMaxRequested(); + printf ("Maximum allocated = %d\nMaximum in use = %d\nIn use at max allocated = %d\n", amax, umax, getInUseAtMaxAllocated()); + printf ("Still in use = %d\n", _currentRequested); + printf ("Fragmentation (3) = %f\n", (float) amax / (float) getInUseAtMaxAllocated()); + printf ("Fragmentation (4) = %f\n", (float) amax / (float) umax); +#endif + +#endif // HEAP_STATS +#if HEAP_LOG + printf ("closing logs.\n"); + fflush (stdout); + for (int i = 0; i < MAX_HEAPS + 1; i++) { + _log[i].close(); + } +#endif +} + + + +#if HEAP_FRAG_STATS +void processHeap::setAllocated (int requestedSize, + int actualSize) +{ + hoardLock (_statsLock); + _currentRequested += requestedSize; + _currentAllocated += actualSize; + if (_currentRequested > _maxRequested) { + _maxRequested = _currentRequested; + } + if (_currentAllocated > _maxAllocated) { + _maxAllocated = _currentAllocated; + _inUseAtMaxAllocated = _currentRequested; + } + hoardUnlock (_statsLock); +} + + +void processHeap::setDeallocated (int requestedSize, + int actualSize) +{ + hoardLock (_statsLock); + _currentRequested -= requestedSize; + _currentAllocated -= actualSize; + hoardUnlock (_statsLock); +} +#endif + + +// free (ptr, pheap): +// inputs: a pointer to an object allocated by malloc(). +// side effects: returns the block to the object's superblock; +// updates the thread heap's statistics; +// may release the superblock to the process heap. + +void processHeap::free (void * ptr) +{ + + // Return if ptr is 0. + // This is the behavior prescribed by the standard. + if (ptr == 0) { + return; + } + + // Find the block and superblock corresponding to this ptr. + + block * b = (block *) ptr - 1; + assert (b->isValid()); + + // Check to see if this block came from a memalign() call. + if (((unsigned long) b->getNext() & 1) == 1) { + // It did. Set the block to the actual block header. + b = (block *) ((unsigned long) b->getNext() & ~1); + assert (b->isValid()); + } + + b->markFree(); + + superblock * sb = b->getSuperblock(); + assert (sb); + assert (sb->isValid()); + + const int sizeclass = sb->getBlockSizeClass(); + + // + // Return the block to the superblock, + // find the heap that owns this superblock + // and update its statistics. + // + + hoardHeap * owner; + + // By acquiring the up lock on the superblock, + // we prevent it from moving to the global heap. + // This eventually pins it down in one heap, + // so this loop is guaranteed to terminate. + // (It should generally take no more than two iterations.) + sb->upLock(); + while (1) { + owner = sb->getOwner(); + owner->lock(); + if (owner == sb->getOwner()) { + break; + } else { + owner->unlock(); + } + // Suspend to allow ownership to quiesce. + hoardYield(); + } + +#if HEAP_LOG + MemoryRequest m; + m.free (ptr); + getLog (owner->getIndex()).append(m); +#endif +#if HEAP_FRAG_STATS + setDeallocated (b->getRequestedSize(), 0); +#endif + + int sbUnmapped = owner->freeBlock (b, sb, sizeclass, this); + + owner->unlock(); + if (!sbUnmapped) { + sb->upUnlock(); + } +} diff --git a/src/kernel/libroot/posix/malloc/processheap.h b/src/kernel/libroot/posix/malloc/processheap.h new file mode 100644 index 0000000000..d39d57e34d --- /dev/null +++ b/src/kernel/libroot/posix/malloc/processheap.h @@ -0,0 +1,267 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +/* + processheap.h + ------------------------------------------------------------------------ + We use one processHeap for the whole program. + ------------------------------------------------------------------------ + @(#) $Id: processheap.h,v 1.1 2002/10/05 17:13:30 axeld Exp $ + ------------------------------------------------------------------------ + Emery Berger | + Department of Computer Sciences | + University of Texas at Austin | + ======================================================================== +*/ + +#ifndef _PROCESSHEAP_H_ +#define _PROCESSHEAP_H_ + +#include "config.h" + +#include +#include + +#include "arch-specific.h" +#include "heap.h" +#if USE_PRIVATE_HEAPS +#include "privateheap.h" +#define HEAPTYPE privateHeap +#else +#define HEAPTYPE threadHeap +#include "threadheap.h" +#endif + +#if HEAP_LOG +#include "memstat.h" +#include "log.h" +#endif + +class processHeap : public hoardHeap { + +public: + + // Always grab at least this many superblocks' worth of memory which + // we parcel out. + enum { REFILL_NUMBER_OF_SUPERBLOCKS = 16 }; + + processHeap (void); + + ~processHeap (void) { +#if HEAP_STATS + stats(); +#endif + } + + // Memory deallocation routines. + void free (void * ptr); + + // Print out statistics information. + void stats (void); + + // Get a thread heap index. + inline int getHeapIndex (void); + + // Get the thread heap with index i. + inline HEAPTYPE& getHeap (int i); + + // Extract a superblock. + inline superblock * acquire (const int c, + hoardHeap * dest); + + // Get space for a superblock. + inline char * getSuperblockBuffer (void); + + // Insert a superblock. + inline void release (superblock * sb); + +#if HEAP_LOG + // Get the log for index i. + inline Log& getLog (int i); +#endif + +#if HEAP_FRAG_STATS + // Declare that we have allocated an object. + void setAllocated (int requestedSize, + int actualSize); + + // Declare that we have deallocated an object. + void setDeallocated (int requestedSize, + int actualSize); + + // Return the number of wasted bytes at the high-water mark + // (maxAllocated - maxRequested) + inline int getFragmentation (void); + + int getMaxAllocated (void) { + return _maxAllocated; + } + + int getInUseAtMaxAllocated (void) { + return _inUseAtMaxAllocated; + } + + int getMaxRequested (void) { + return _maxRequested; + } + +#endif + +private: + + // Hide the lock & unlock methods. + + void lock (void) { + hoardHeap::lock(); + } + + void unlock (void) { + hoardHeap::unlock(); + } + + // Prevent copying and assignment. + processHeap (const processHeap&); + const processHeap& operator= (const processHeap&); + + // The per-thread heaps. + HEAPTYPE theap[MAX_HEAPS]; + +#if HEAP_FRAG_STATS + // Statistics required to compute fragmentation. We cannot + // unintrusively keep track of these on a multiprocessor, because + // this would become a bottleneck. + + int _currentAllocated; + int _currentRequested; + int _maxAllocated; + int _maxRequested; + int _inUseAtMaxAllocated; + int _fragmentation; + + // A lock to protect these statistics. + hoardLockType _statsLock; +#endif + +#if HEAP_LOG + Log _log[MAX_HEAPS + 1]; +#endif + + // A lock for the superblock buffer. + hoardLockType _bufferLock; + + char * _buffer; + int _bufferCount; +}; + + +HEAPTYPE& processHeap::getHeap (int i) +{ + assert (i >= 0); + assert (i < MAX_HEAPS); + return theap[i]; +} + + +#if HEAP_LOG +Log& processHeap::getLog (int i) +{ + assert (i >= 0); + assert (i < MAX_HEAPS + 1); + return _log[i]; +} +#endif + + +#ifdef NEED_LG +// Return ceil(log_2(num)). +// num must be positive. +static int lg (int num) +{ + assert (num > 0); + int power = 0; + int n = 1; + // Invariant: 2^power == n. + while (n < num) { + n <<= 1; + power++; + } + return power; +} +#endif /* NEED_LG */ + +// Hash out the thread id to a heap and return an index to that heap. +int processHeap::getHeapIndex (void) { + // Here we use the number of processors as the maximum number of heaps. + // In fact, for efficiency, we just round up to the highest power of two, + // times two. + int tid = hoardGetThreadID() & _numProcessorsMask; + assert (tid < MAX_HEAPS); + return tid; +} + + +superblock * processHeap::acquire (const int sizeclass, + hoardHeap * dest) +{ + lock (); + + // Remove the superblock with the most free space. + superblock * maxSb = removeMaxSuperblock (sizeclass); + if (maxSb) { + maxSb->setOwner (dest); + } + + unlock (); + + return maxSb; +} + + +inline char * processHeap::getSuperblockBuffer (void) +{ + char * buf; + hoardLock (_bufferLock); + if (_bufferCount == 0) { + _buffer = (char *) hoardSbrk (SUPERBLOCK_SIZE * REFILL_NUMBER_OF_SUPERBLOCKS); + _bufferCount = REFILL_NUMBER_OF_SUPERBLOCKS; + } + buf = _buffer; + _buffer += SUPERBLOCK_SIZE; + _bufferCount--; + hoardUnlock (_bufferLock); + return buf; +} + + +// Put a superblock back into our list of superblocks. +void processHeap::release (superblock * sb) +{ + assert (EMPTY_FRACTION * sb->getNumAvailable() > sb->getNumBlocks()); + + lock(); + + // Insert the superblock. + insertSuperblock (sb->getBlockSizeClass(), sb, this); + + unlock(); +} + + +#endif // _PROCESSHEAP_H_ + diff --git a/src/kernel/libroot/posix/malloc/superblock.cpp b/src/kernel/libroot/posix/malloc/superblock.cpp new file mode 100644 index 0000000000..0065c352e7 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/superblock.cpp @@ -0,0 +1,132 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// The Hoard Multiprocessor Memory Allocator +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +/* + superblock.cpp + ------------------------------------------------------------------------ + The superblock class controls a number of blocks (which are + allocatable units of memory). + ------------------------------------------------------------------------ + @(#) $Id: superblock.cpp,v 1.1 2002/10/05 17:13:30 axeld Exp $ + ------------------------------------------------------------------------ + Emery Berger | + Department of Computer Sciences | + University of Texas at Austin | + ======================================================================== +*/ + +//#include +#include + +#include "arch-specific.h" +#include "config.h" +#include "heap.h" +#include "processheap.h" +#include "superblock.h" + + +superblock::superblock (int numBlocks, // The number of blocks in the sb. + int szclass, // The size class of the blocks. + hoardHeap * o) // The heap that "owns" this sb. + : +#if HEAP_DEBUG + _magic (SUPERBLOCK_MAGIC), +#endif + _sizeClass (szclass), + _numBlocks (numBlocks), + _numAvailable (0), + _fullness (0), + _freeList (NULL), + _owner (o), + _next (NULL), + _prev (NULL) +{ + assert (_numBlocks >= 1); + + // Determine the size of each block. + const int blksize = + hoardHeap::align (sizeof(block) + hoardHeap::sizeFromClass(_sizeClass)); + + // Make sure this size is in fact aligned. + assert ((blksize & hoardHeap::ALIGNMENT_MASK) == 0); + + // Set the first block to just past this superblock header. + block * b + = (block *) hoardHeap::align ((unsigned long) (this + 1)); + + // Initialize all the blocks, + // and insert the block pointers into the linked list. + for (int i = 0; i < _numBlocks; i++) { + // Make sure the block is on a double-word boundary. + assert (((unsigned int) b & hoardHeap::ALIGNMENT_MASK) == 0); + new (b) block (this); + assert (b->getSuperblock() == this); + b->setNext (_freeList); + _freeList = b; + b = (block *) ((char *) b + blksize); + } + _numAvailable = _numBlocks; + computeFullness(); + assert ((unsigned long) b <= hoardHeap::align (sizeof(superblock) + blksize * _numBlocks) + (unsigned long) this); + + hoardLockInit (_upLock); +} + +superblock * superblock::makeSuperblock (int sizeclass, + processHeap * pHeap) +{ + // We need to get more memory. + + char * buf; + int numBlocks = hoardHeap::numBlocks(sizeclass); + + // Compute how much memory we need. + unsigned long moreMemory; + if (numBlocks > 1) { + moreMemory = hoardHeap::SUPERBLOCK_SIZE; + assert (moreMemory >= hoardHeap::align(sizeof(superblock) + (hoardHeap::align (sizeof(block) + hoardHeap::sizeFromClass(sizeclass))) * numBlocks)); + + // Get some memory from the process heap. + buf = (char *) pHeap->getSuperblockBuffer(); + + } else { + // One object. + assert (numBlocks == 1); + + size_t blksize = hoardHeap::align (sizeof(block) + hoardHeap::sizeFromClass(sizeclass)); + moreMemory = hoardHeap::align (sizeof(superblock) + blksize); + + // Get space from the system. + buf = (char *) hoardSbrk (moreMemory); + } + + // Make sure that we actually got the memory. + if (buf == NULL) { + return 0; + } + buf = (char *) hoardHeap::align ((unsigned long) buf); + + // Make sure this buffer is double-word aligned. + assert (buf == (char *) hoardHeap::align ((unsigned long) buf)); + assert ((((unsigned long) buf) & hoardHeap::ALIGNMENT_MASK) == 0); + + // Instantiate the new superblock in the buffer. + superblock * sb = new (buf) superblock (numBlocks, sizeclass, NULL); + + return sb; +} diff --git a/src/kernel/libroot/posix/malloc/superblock.h b/src/kernel/libroot/posix/malloc/superblock.h new file mode 100644 index 0000000000..e9a917ebfb --- /dev/null +++ b/src/kernel/libroot/posix/malloc/superblock.h @@ -0,0 +1,287 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +/* + superblock.h + ------------------------------------------------------------------------ + The superblock class controls a number of blocks (which are + allocatable units of memory). + ------------------------------------------------------------------------ + @(#) $Id: superblock.h,v 1.1 2002/10/05 17:13:30 axeld Exp $ + ------------------------------------------------------------------------ + Emery Berger | + Department of Computer Sciences | + University of Texas at Austin | + ======================================================================== +*/ + +#ifndef _SUPERBLOCK_H_ +#define _SUPERBLOCK_H_ + +#include "config.h" + +//#include +//#include +//#include +//#include + +#include "arch-specific.h" +#include "block.h" + +class hoardHeap; // forward declaration +class processHeap; // forward declaration + +class superblock { + +public: + + // Construct a superblock for a given size class and set the heap + // owner. + superblock (int numblocks, + int sizeclass, + hoardHeap * owner); + + ~superblock (void) + {} + + // Make (allocate or re-use) a superblock for a given size class. + static superblock * makeSuperblock (int sizeclass, processHeap * pHeap); + + // Find out who allocated this superblock. + inline hoardHeap * getOwner (void); + + // Set the superblock's owner. + inline void setOwner (hoardHeap * o); + + // Get a block from the superblock. + inline block * getBlock (void); + + // Put a block back in the superblock. + inline void putBlock (block * b); + + // How many blocks are available? + inline int getNumAvailable (void); + + // How many blocks are there, in total? + inline int getNumBlocks (void); + + // What size class are blocks in this superblock? + inline int getBlockSizeClass (void); + + // Insert this superblock before the next one. + inline void insertBefore (superblock * nextSb); + + // Return the next pointer (to the next superblock in the list). + inline superblock * const getNext (void); + + // Return the prev pointer (to the previous superblock in the list). + inline superblock * const getPrev (void); + + // Compute the 'fullness' of this superblock. + inline void computeFullness (void); + + // Return the 'fullness' of this superblock. + inline int getFullness (void); + +#if HEAP_FRAG_STATS + // Return the amount of waste in every allocated block. + int getMaxInternalFragmentation (void); +#endif + + // Remove this superblock from its linked list. + inline void remove (void); + + // Is this superblock valid? (i.e., + // does it have the right magic number?) + inline int isValid (void); + + void upLock (void) { + hoardLock (_upLock); + } + + void upUnlock (void) { + hoardUnlock (_upLock); + } + +private: + + // Disable copying and assignment. + + superblock (const superblock&); + const superblock& operator= (const superblock&); + + // Used for sanity checking. + enum { SUPERBLOCK_MAGIC = 0xCAFEBABE }; + +#if HEAP_DEBUG + unsigned long _magic; +#endif + + const int _sizeClass; // The size class of blocks in the superblock. + const int _numBlocks; // The number of blocks in the superblock. + int _numAvailable; // The number of blocks available. + int _fullness; // How full is this superblock? + // (which SUPERBLOCK_FULLNESS group is it in) + block * _freeList; // A pointer to the first free block. + hoardHeap * _owner; // The heap who owns this superblock. + superblock * _next; // The next superblock in the list. + superblock * _prev; // The previous superblock in the list. + + hoardLockType _upLock; // Lock this when moving a superblock to the global (process) heap. + + // We insert a cache pad here to prevent false sharing with the + // first block (which immediately follows the superblock). + + double _pad[CACHE_LINE / sizeof(double)]; +}; + + +hoardHeap * superblock::getOwner (void) +{ + assert (isValid()); + hoardHeap * o = _owner; + return o; +} + + +void superblock::setOwner (hoardHeap * o) +{ + assert (isValid()); + _owner = o; +} + + +block * superblock::getBlock (void) +{ + assert (isValid()); + // Pop off a block from this superblock's freelist, + // if there is one available. + if (_freeList == NULL) { + // The freelist is empty. + assert (getNumAvailable() == 0); + return NULL; + } + assert (getNumAvailable() > 0); + block * b = _freeList; + _freeList = _freeList->getNext(); + _numAvailable--; + + b->setNext(NULL); + + computeFullness(); + + return b; +} + + +void superblock::putBlock (block * b) +{ + assert (isValid()); + // Push a block onto the superblock's freelist. + assert (b->isValid()); + assert (b->getSuperblock() == this); + assert (getNumAvailable() < getNumBlocks()); + b->setNext (_freeList); + _freeList = b; + _numAvailable++; + computeFullness(); +} + +int superblock::getNumAvailable (void) +{ + assert (isValid()); + return _numAvailable; +} + + +int superblock::getNumBlocks (void) +{ + assert (isValid()); + return _numBlocks; +} + + +int superblock::getBlockSizeClass (void) +{ + assert (isValid()); + return _sizeClass; +} + + +superblock * const superblock::getNext (void) +{ + assert (isValid()); + return _next; +} + +superblock * const superblock::getPrev (void) +{ + assert (isValid()); + return _prev; +} + + +void superblock::insertBefore (superblock * nextSb) { + assert (isValid()); + // Insert this superblock before the next one (nextSb). + assert (nextSb != this); + _next = nextSb; + if (nextSb) { + _prev = nextSb->_prev; + nextSb->_prev = this; + } +} + + +void superblock::remove (void) { + // Remove this superblock from a doubly-linked list. + if (_next) { + _next->_prev = _prev; + } + if (_prev) { + _prev->_next = _next; + } + _prev = NULL; + _next = NULL; +} + + +int superblock::isValid (void) +{ + assert (_numBlocks > 0); + assert (_numAvailable <= _numBlocks); + assert (_sizeClass >= 0); + return 1; +} + + +void superblock::computeFullness (void) +{ + assert (isValid()); + _fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1) + * (getNumBlocks() - getNumAvailable())) / getNumBlocks()); +} + +int superblock::getFullness (void) +{ + assert (isValid()); + return _fullness; +} + +#endif // _SUPERBLOCK_H_ diff --git a/src/kernel/libroot/posix/malloc/threadheap.cpp b/src/kernel/libroot/posix/malloc/threadheap.cpp new file mode 100644 index 0000000000..40675dcaa3 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/threadheap.cpp @@ -0,0 +1,110 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +//#include +#include + +#include "config.h" + +#include "heap.h" +#include "threadheap.h" +#include "processheap.h" + + +threadHeap::threadHeap (void) + : _pHeap (0) +{} + + +// malloc (sz): +// inputs: the size of the object to be allocated. +// returns: a pointer to an object of the appropriate size. +// side effects: allocates a block from a superblock; +// may call sbrk() (via makeSuperblock). + +void * threadHeap::malloc (const size_t size) +{ + const int sizeclass = sizeClass (size); + block * b = NULL; + + lock(); + + // Look for a free block. + // We usually have memory locally so we first look for space in the + // superblock list. + + superblock * sb = findAvailableSuperblock (sizeclass, b, _pHeap); + + if (sb == NULL) { + + // We don't have memory locally. + // Try to get more from the process heap. + + assert (_pHeap); + sb = _pHeap->acquire ((int) sizeclass, this); + + // If we didn't get any memory from the process heap, + // we'll have to allocate our own superblock. + if (sb == NULL) { + sb = superblock::makeSuperblock (sizeclass, _pHeap); + if (sb == NULL) { + // We're out of memory! + unlock (); + return NULL; + } +#if HEAP_LOG + // Record the memory allocation. + MemoryRequest m; + m.allocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass())); + _pHeap->getLog(getIndex()).append(m); +#endif +#if HEAP_FRAG_STATS + _pHeap->setAllocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass())); +#endif + } + + // Get a block from the superblock. + b = sb->getBlock (); + assert (b != NULL); + + // Insert the superblock into our list. + insertSuperblock (sizeclass, sb, _pHeap); + } + + assert (b != NULL); + assert (b->isValid()); + assert (sb->isValid()); + + b->markAllocated(); + +#if HEAP_LOG + MemoryRequest m; + m.malloc ((void *) (b + 1), align(size)); + _pHeap->getLog(getIndex()).append(m); +#endif +#if HEAP_FRAG_STATS + b->setRequestedSize (align(size)); + _pHeap->setAllocated (align(size), 0); +#endif + + unlock(); + + // Skip past the block header and return the pointer. + return (void *) (b + 1); +} diff --git a/src/kernel/libroot/posix/malloc/threadheap.h b/src/kernel/libroot/posix/malloc/threadheap.h new file mode 100644 index 0000000000..2f113b272b --- /dev/null +++ b/src/kernel/libroot/posix/malloc/threadheap.h @@ -0,0 +1,168 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef _THREADHEAP_H_ +#define _THREADHEAP_H_ + +#include "config.h" + +#include + +#include "heap.h" + +class processHeap; // forward declaration + +// +// We use one threadHeap for each thread (processor). +// + +class threadHeap : public hoardHeap { + +public: + + threadHeap (void); + + // Memory allocation routines. + void * malloc (const size_t sz); + inline void * memalign (size_t alignment, size_t sz); + + // Find out how large an allocated object is. + inline static size_t objectSize (void * ptr); + + // Set our process heap. + inline void setpHeap (processHeap * p); + +private: + + // Prevent copying and assignment. + threadHeap (const threadHeap&); + const threadHeap& operator= (const threadHeap&); + + // Our process heap. + processHeap * _pHeap; + + // We insert a cache pad here to avoid false sharing (the + // processHeap holds an array of threadHeaps, and we don't want + // these to share any cache lines). + double _pad[CACHE_LINE / sizeof(double)]; +}; + + +void * threadHeap::memalign (size_t alignment, + size_t size) +{ + // Calculate the amount of space we need + // to satisfy the alignment requirements. + + size_t newSize; + + // If the alignment is less than the required alignment, + // just call malloc. + if (alignment <= ALIGNMENT) { + return this->malloc (size); + } + + if (alignment < sizeof(block)) { + alignment = sizeof(block); + } + + // Alignment must be a power of two! + assert ((alignment & (alignment - 1)) == 0); + + // Leave enough room to align the block within the malloced space. + newSize = size + sizeof(block) + alignment; + + // Now malloc the space up with a little extra (we'll put the block + // pointer in right behind the allocated space). + + void * ptr = this->malloc (newSize); + if ((((unsigned long) ptr) & -((long) alignment)) == 0) { + // ptr is already aligned, so return it. + assert (((unsigned long) ptr % alignment) == 0); + return ptr; + + } else { + + // Align ptr. + char * newptr = (char *) + (((unsigned long) ptr + alignment - 1) & -((long) alignment)); + + // If there's not enough room for the block header, skip to the + // next aligned space within the block.. + if ((unsigned long) newptr - (unsigned long) ptr < sizeof(block)) { + newptr += alignment; + } + assert (((unsigned long) newptr % alignment) == 0); + + // Copy the block from the start of the allocated memory. + block * b = ((block *) ptr - 1); + + assert (b->isValid()); + assert (b->getSuperblock()->isValid()); + + // Make sure there's enough room for the block header. + assert (((unsigned long) newptr - (unsigned long) ptr) >= sizeof(block)); + + block * p = ((block *) newptr - 1); + + // Make sure there's enough room allocated for size bytes. + assert (((unsigned long) p - sizeof(block)) >= (unsigned long) b); + + if (p != b) { + assert ((unsigned long) newptr > (unsigned long) ptr); + // Copy the block header. + *p = *b; + assert (p->isValid()); + assert (p->getSuperblock()->isValid()); + + // Set the next pointer to point to b with the 1 bit set. + // When this block is freed, it will be treated specially. + p->setNext ((block *) ((unsigned long) b | 1)); + + } else { + assert (ptr != newptr); + } + + assert (((unsigned long) ptr + newSize) >= ((unsigned long) newptr + size)); + return newptr; + } +} + + +size_t threadHeap::objectSize (void * ptr) +{ + // Find the superblock pointer. + + block * b = ((block *) ptr - 1); + assert (b->isValid()); + superblock * sb = b->getSuperblock (); + assert (sb); + + // Return the size. + return sizeFromClass (sb->getBlockSizeClass()); +} + + +void threadHeap::setpHeap (processHeap * p) +{ + _pHeap = p; +} + +#endif // _THREADHEAP_H_ + diff --git a/src/kernel/libroot/posix/malloc/wrapper.cpp b/src/kernel/libroot/posix/malloc/wrapper.cpp new file mode 100644 index 0000000000..9fcadbec80 --- /dev/null +++ b/src/kernel/libroot/posix/malloc/wrapper.cpp @@ -0,0 +1,269 @@ +///-*-C++-*-////////////////////////////////////////////////////////////////// +// +// Hoard: A Fast, Scalable, and Memory-Efficient Allocator +// for Shared-Memory Multiprocessors +// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery +// +// Copyright (c) 1998-2000, The University of Texas at Austin. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License as +// published by the Free Software Foundation, http://www.fsf.org. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +////////////////////////////////////////////////////////////////////////////// + +/* + wrapper.cpp + ------------------------------------------------------------------------ + Implementations of malloc(), free(), etc. in terms of hoard. + This lets us link in hoard in place of the stock malloc + (useful to test fragmentation). + ------------------------------------------------------------------------ + @(#) $Id: wrapper.cpp,v 1.1 2002/10/05 17:13:30 axeld Exp $ + ------------------------------------------------------------------------ + Emery Berger | + Department of Computer Sciences | + University of Texas at Austin | + ======================================================================== +*/ + +#include +#include "config.h" + +#if USE_PRIVATE_HEAPS +#include "privateheap.h" +#define HEAPTYPE privateHeap +#else +#include "threadheap.h" +#define HEAPTYPE threadHeap +#endif + +#include "processheap.h" +#include "arch-specific.h" + + +inline static processHeap * getAllocator (void) { + static char * buf = (char *) hoardSbrk (sizeof(processHeap)); + static processHeap * theAllocator = new (buf) processHeap; + return theAllocator; +} + +#define HOARD_MALLOC(x) malloc(x) +#define HOARD_FREE(x) free(x) +#define HOARD_REALLOC(x,y) realloc(x,y) +#define HOARD_CALLOC(x,y) calloc(x,y) +#define HOARD_MEMALIGN(x,y) memalign(x,y) +#define HOARD_VALLOC(x) valloc(x) + +extern "C" void * HOARD_MALLOC(size_t); +extern "C" void HOARD_FREE(void *); +extern "C" void * HOARD_REALLOC(void *, size_t); +extern "C" void * HOARD_CALLOC(size_t, size_t); +extern "C" void * HOARD_MEMALIGN(size_t, size_t); +extern "C" void * HOARD_VALLOC(size_t); + + +void * operator new (size_t size) +{ + return HOARD_MALLOC (size); +} +/* +void * operator new (size_t size, const std::nothrow_t&) throw() { + return HOARD_MALLOC (size); +} +*/ +void * operator new[] (size_t size) +{ + return HOARD_MALLOC (size); +} +/* +void * operator new[] (size_t size, const std::nothrow_t&) throw() { + return HOARD_MALLOC (size); +} +*/ +void operator delete (void * ptr) +{ + HOARD_FREE (ptr); +} + +void operator delete[] (void * ptr) +{ + HOARD_FREE (ptr); +} + + +extern "C" void * HOARD_MALLOC (size_t sz) +{ + static processHeap * pHeap = getAllocator(); + void * addr = pHeap->getHeap(pHeap->getHeapIndex()).malloc (sz); + return addr; +} + +extern "C" void * HOARD_CALLOC (size_t nelem, size_t elsize) +{ + static processHeap * pHeap = getAllocator(); + void * ptr = pHeap->getHeap(pHeap->getHeapIndex()).malloc (nelem * elsize); + // Zero out the malloc'd block. + memset (ptr, 0, nelem * elsize); + return ptr; +} + +extern "C" void HOARD_FREE (void * ptr) +{ + static processHeap * pHeap = getAllocator(); +#if USE_PRIVATE_HEAPS + pHeap->getHeap(pHeap->getHeapIndex()).free(ptr); +#else + pHeap->free (ptr); +#endif +} + + +extern "C" void * HOARD_MEMALIGN (size_t alignment, size_t size) +{ + static processHeap * pHeap = getAllocator(); + void * addr = pHeap->getHeap(pHeap->getHeapIndex()).memalign (alignment, size); + return addr; +} + + +extern "C" void * HOARD_VALLOC (size_t size) +{ + return HOARD_MEMALIGN (hoardGetPageSize(), size); +} + + +extern "C" void * HOARD_REALLOC (void * ptr, size_t sz) +{ + if (ptr == NULL) { + return HOARD_MALLOC (sz); + } + if (sz == 0) { + HOARD_FREE (ptr); + return NULL; + } + + // If the existing object can hold the new size, + // just return it. + + size_t objSize = HEAPTYPE::objectSize (ptr); + + if (objSize >= sz) { + return ptr; + } + + // Allocate a new block of size sz. + + void * buf = HOARD_MALLOC (sz); + + // Copy the contents of the original object + // up to the size of the new block. + + size_t minSize = (objSize < sz) ? objSize : sz; + memcpy (buf, ptr, minSize); + + // Free the old block. + + HOARD_FREE (ptr); + + // Return a pointer to the new one. + + return buf; +} + + +#ifdef WIN32 + +// Replace the CRT debugging allocation routines, just to be on the safe side. +// This is not a complete solution, but should avoid inadvertent mixing of allocations. + +extern "C" void * _malloc_dbg (size_t sz, int, const char *, int) { + return HOARD_MALLOC (sz); +} + +void * operator new( + unsigned int cb, + int nBlockUse, + const char * szFileName, + int nLine + ) +{ + return HOARD_MALLOC (cb); +} + +extern "C" void * _calloc_dbg (size_t num, size_t size, int, const char *, int) { + return HOARD_CALLOC (num, size); +} + +extern "C" void * _realloc_dbg (void * ptr, size_t newSize, int, const char *, int) { + return HOARD_REALLOC (ptr, newSize); +} + +extern "C" void _free_dbg (void * ptr, int) { + HOARD_FREE (ptr); +} + +extern "C" size_t _msize_dbg (void * ptr) { + // Find the block and superblock corresponding to this ptr. + + block * b = (block *) ptr - 1; + assert (b->isValid()); + + // Check to see if this block came from a memalign() call. + if (((unsigned long) b->getNext() & 1) == 1) { + // It did. Set the block to the actual block header. + b = (block *) ((unsigned long) b->getNext() & ~1); + assert (b->isValid()); + } + + superblock * sb = b->getSuperblock(); + assert (sb); + assert (sb->isValid()); + + const int sizeclass = sb->getBlockSizeClass(); + return hoardHeap::sizeFromClass (sizeclass); +} + +extern "C" size_t _msize (void * ptr) { + // Find the block and superblock corresponding to this ptr. + + block * b = (block *) ptr - 1; + assert (b->isValid()); + + // Check to see if this block came from a memalign() call. + if (((unsigned long) b->getNext() & 1) == 1) { + // It did. Set the block to the actual block header. + b = (block *) ((unsigned long) b->getNext() & ~1); + assert (b->isValid()); + } + + superblock * sb = b->getSuperblock(); + assert (sb); + assert (sb->isValid()); + + const int sizeclass = sb->getBlockSizeClass(); + return hoardHeap::sizeFromClass (sizeclass); +} + +extern "C" void * _nh_malloc_base (size_t sz, int) { + return HOARD_MALLOC (sz); +} + +extern "C" void * _nh_malloc_dbg (size_t sz, size_t, int, int, const char *, int) { + return HOARD_MALLOC (sz); +} + +#endif // WIN32 + + +#if 0 +extern "C" void malloc_stats (void) +{ + TheWrapper.TheAllocator()->stats(); +} +#endif diff --git a/src/kernel/libroot/posix/math/Jamfile b/src/kernel/libroot/posix/math/Jamfile new file mode 100644 index 0000000000..5d8ab83cb3 --- /dev/null +++ b/src/kernel/libroot/posix/math/Jamfile @@ -0,0 +1,38 @@ +SubDir OBOS_TOP src kernel libroot posix math ; + +KernelObjects + <$(SOURCE_GRIST)>acosh.c + <$(SOURCE_GRIST)>asincos.c + <$(SOURCE_GRIST)>asinh.c + <$(SOURCE_GRIST)>atan.c + <$(SOURCE_GRIST)>atan2.c + <$(SOURCE_GRIST)>atanh.c + <$(SOURCE_GRIST)>cabs.c + <$(SOURCE_GRIST)>cbrt.c + <$(SOURCE_GRIST)>cosh.c + <$(SOURCE_GRIST)>erf.c + <$(SOURCE_GRIST)>exp.c + <$(SOURCE_GRIST)>exp__E.c + <$(SOURCE_GRIST)>expm1.c + <$(SOURCE_GRIST)>floor.c + <$(SOURCE_GRIST)>fmod.c + <$(SOURCE_GRIST)>gamma.c + <$(SOURCE_GRIST)>ieee.c + <$(SOURCE_GRIST)>j0.c + <$(SOURCE_GRIST)>j1.c + <$(SOURCE_GRIST)>jn.c + <$(SOURCE_GRIST)>lgamma.c + <$(SOURCE_GRIST)>log.c + <$(SOURCE_GRIST)>log10.c + <$(SOURCE_GRIST)>log1p.c + <$(SOURCE_GRIST)>log__L.c + <$(SOURCE_GRIST)>pow.c + <$(SOURCE_GRIST)>sincos.c + <$(SOURCE_GRIST)>sinh.c + <$(SOURCE_GRIST)>tan.c + <$(SOURCE_GRIST)>tanh.c + : + -fPIC -DPIC + ; + +SubInclude OBOS_TOP src kernel libroot posix math arch ; diff --git a/src/kernel/libroot/posix/math/acosh.c b/src/kernel/libroot/posix/math/acosh.c new file mode 100644 index 0000000000..dbe0d2896a --- /dev/null +++ b/src/kernel/libroot/posix/math/acosh.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* ACOSH(X) + * RETURN THE INVERSE HYPERBOLIC COSINE OF X + * DOUBLE PRECISION (VAX D FORMAT 56 BITS, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 2/16/85; + * REVISED BY K.C. NG on 3/6/85, 3/24/85, 4/16/85, 8/17/85. + * + * Required system supported functions : + * sqrt(x) + * + * Required kernel function: + * log1p(x) ...return log(1+x) + * + * Method : + * Based on + * acosh(x) = log [ x + sqrt(x*x-1) ] + * we have + * acosh(x) := log1p(x)+ln2, if (x > 1.0E20); else + * acosh(x) := log1p( sqrt(x-1) * (sqrt(x-1) + sqrt(x+1)) ) . + * These formulae avoid the over/underflow complication. + * + * Special cases: + * acosh(x) is NaN with signal if x<1. + * acosh(NaN) is NaN without signal. + * + * Accuracy: + * acosh(x) returns the exact inverse hyperbolic cosine of x nearly + * rounded. In a test run with 512,000 random arguments on a VAX, the + * maximum observed error was 3.30 ulps (units of the last place) at + * x=1.0070493753568216 . + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000) +vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC) + +ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000) +ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76) + +#ifdef vccast +#define ln2hi vccast(ln2hi) +#define ln2lo vccast(ln2lo) +#endif + +double acosh(x) +double x; +{ + double t,big=1.E20; /* big+1==big */ + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + + /* return log1p(x) + log(2) if x is large */ + if(x>big) {t=log1p(x)+ln2lo; return(t+ln2hi);} + + t=sqrt(x-1.0); + return(log1p(t*(t+sqrt(x+1.0)))); +} diff --git a/src/kernel/libroot/posix/math/arch/Jamfile b/src/kernel/libroot/posix/math/arch/Jamfile new file mode 100644 index 0000000000..e4c0f3eefc --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/Jamfile @@ -0,0 +1,3 @@ +SubDir OBOS_TOP src kernel libroot posix math arch ; + +SubInclude OBOS_TOP src kernel libroot posix math arch $(OBOS_TARGET_DIR) ; diff --git a/src/kernel/libroot/posix/math/arch/sh4/Jamfile b/src/kernel/libroot/posix/math/arch/sh4/Jamfile new file mode 100644 index 0000000000..508feb3e43 --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/sh4/Jamfile @@ -0,0 +1,3 @@ +SubDir OBOS_TOP src kernel libroot posix math arch sh4 ; + +KernelStaticLibrary libmsh4 : fabs.S frexp.c isinf.c ldexp.c ; diff --git a/src/kernel/libroot/posix/math/arch/sh4/fabs.S b/src/kernel/libroot/posix/math/arch/sh4/fabs.S new file mode 100644 index 0000000000..7cac138f31 --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/sh4/fabs.S @@ -0,0 +1,10 @@ +/* +** Copyright 2002, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#define FUNCTION(name) .align 2 ; .globl _##name ; .type _##name,@function ; _##name + +FUNCTION(fabs): + fabs dr4 + rts + fmov dr4,dr0 diff --git a/src/kernel/libroot/posix/math/arch/sh4/frexp.c b/src/kernel/libroot/posix/math/arch/sh4/frexp.c new file mode 100644 index 0000000000..a75ed58b09 --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/sh4/frexp.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/i386/gen/frexp.c,v 1.5 1999/08/27 23:59:21 peter Exp $ + */ + +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = "$FreeBSD: src/lib/libc/i386/gen/frexp.c,v 1.5 1999/08/27 23:59:21 peter Exp $"; +#endif /* LIBC_RCS and not lint */ + +#include + +double +frexp(value, eptr) + double value; + int *eptr; +{ + union { + double v; + struct { + unsigned u_mant2 : 32; + unsigned u_mant1 : 20; + unsigned u_exp : 11; + unsigned u_sign : 1; + } s; + } u; + + if (value) { + u.v = value; + *eptr = u.s.u_exp - 1022; + u.s.u_exp = 1022; + return(u.v); + } else { + *eptr = 0; + return((double)0); + } +} diff --git a/src/kernel/libroot/posix/math/arch/sh4/isinf.c b/src/kernel/libroot/posix/math/arch/sh4/isinf.c new file mode 100644 index 0000000000..9419bff773 --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/sh4/isinf.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/i386/gen/isinf.c,v 1.6 1999/08/27 23:59:21 peter Exp $ + */ + +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = "$FreeBSD: src/lib/libc/i386/gen/isinf.c,v 1.6 1999/08/27 23:59:21 peter Exp $"; +#endif /* LIBC_RCS and not lint */ + +#include +#include + +int +isnan(d) + double d; +{ + register struct IEEEdp { + unsigned manl : 32; + unsigned manh : 20; + unsigned exp : 11; + unsigned sign : 1; + } *p = (struct IEEEdp *)&d; + + return(p->exp == 2047 && (p->manh || p->manl)); +} + +int +isinf(d) + double d; +{ + register struct IEEEdp { + u_int manl : 32; + u_int manh : 20; + u_int exp : 11; + u_int sign : 1; + } *p = (struct IEEEdp *)&d; + + return(p->exp == 2047 && !p->manh && !p->manl); +} diff --git a/src/kernel/libroot/posix/math/arch/sh4/ldexp.c b/src/kernel/libroot/posix/math/arch/sh4/ldexp.c new file mode 100644 index 0000000000..b5ee3499ee --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/sh4/ldexp.c @@ -0,0 +1,12 @@ +#include + +/* + * ldexp(value, exp): return value * (2 ** exp). + */ + +double +ldexp (double value, int exp) +{ + /* XXX Bad */ + return value; +} diff --git a/src/kernel/libroot/posix/math/arch/x86/Jamfile b/src/kernel/libroot/posix/math/arch/x86/Jamfile new file mode 100644 index 0000000000..69c658372b --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/x86/Jamfile @@ -0,0 +1,3 @@ +SubDir OBOS_TOP src kernel libroot posix math arch x86 ; + +KernelObjects fabs.S frexp.c isinf.c ldexp.c ; diff --git a/src/kernel/libroot/posix/math/arch/x86/fabs.S b/src/kernel/libroot/posix/math/arch/x86/fabs.S new file mode 100644 index 0000000000..e95e3f8195 --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/x86/fabs.S @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/i386/gen/fabs.S,v 1.5 1999/08/27 23:59:20 peter Exp $ + */ + +#if defined(LIBC_RCS) && !defined(lint) + .text + .asciz "$FreeBSD: src/lib/libc/i386/gen/fabs.S,v 1.5 1999/08/27 23:59:20 peter Exp $" +#endif /* LIBC_RCS and not lint */ + + +.global fabs +.type fabs,@function +fabs: + fldl 4(%esp) + fabs + ret diff --git a/src/kernel/libroot/posix/math/arch/x86/frexp.c b/src/kernel/libroot/posix/math/arch/x86/frexp.c new file mode 100644 index 0000000000..a75ed58b09 --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/x86/frexp.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/i386/gen/frexp.c,v 1.5 1999/08/27 23:59:21 peter Exp $ + */ + +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = "$FreeBSD: src/lib/libc/i386/gen/frexp.c,v 1.5 1999/08/27 23:59:21 peter Exp $"; +#endif /* LIBC_RCS and not lint */ + +#include + +double +frexp(value, eptr) + double value; + int *eptr; +{ + union { + double v; + struct { + unsigned u_mant2 : 32; + unsigned u_mant1 : 20; + unsigned u_exp : 11; + unsigned u_sign : 1; + } s; + } u; + + if (value) { + u.v = value; + *eptr = u.s.u_exp - 1022; + u.s.u_exp = 1022; + return(u.v); + } else { + *eptr = 0; + return((double)0); + } +} diff --git a/src/kernel/libroot/posix/math/arch/x86/isinf.c b/src/kernel/libroot/posix/math/arch/x86/isinf.c new file mode 100644 index 0000000000..ff32fbd7de --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/x86/isinf.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/i386/gen/isinf.c,v 1.6 1999/08/27 23:59:21 peter Exp $ + */ + +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = "$FreeBSD: src/lib/libc/i386/gen/isinf.c,v 1.6 1999/08/27 23:59:21 peter Exp $"; +#endif /* LIBC_RCS and not lint */ + +#include +#include + +/* ToDo: on BeOS/x86, these are defined as __isnan(), and __isinf() - the + * isnan()/isinf() are only macros - we will have to reflect this here. + */ + +int isnan(double); +int isinf(double); + +int +isnan(double d) +{ + register struct IEEEdp { + unsigned manl : 32; + unsigned manh : 20; + unsigned exp : 11; + unsigned sign : 1; + } *p = (struct IEEEdp *)&d; + + return p->exp == 2047 && (p->manh || p->manl); +} + + +int +isinf(double d) +{ + register struct IEEEdp { + u_int manl : 32; + u_int manh : 20; + u_int exp : 11; + u_int sign : 1; + } *p = (struct IEEEdp *)&d; + + return p->exp == 2047 && !p->manh && !p->manl; +} diff --git a/src/kernel/libroot/posix/math/arch/x86/ldexp.c b/src/kernel/libroot/posix/math/arch/x86/ldexp.c new file mode 100644 index 0000000000..68544e58fa --- /dev/null +++ b/src/kernel/libroot/posix/math/arch/x86/ldexp.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Sean Eric Fagan. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/i386/gen/ldexp.c,v 1.6 1999/08/27 23:59:21 peter Exp $ + */ + +#include + +#if defined(LIBC_RCS) && !defined(lint) +static const char rcsid[] = "$FreeBSD: src/lib/libc/i386/gen/ldexp.c,v 1.6 1999/08/27 23:59:21 peter Exp $"; +#endif /* LIBC_RCS and not lint */ + +/* + * ldexp(value, exp): return value * (2 ** exp). + * + * Written by Sean Eric Fagan (sef@kithrup.COM) + * Sun Mar 11 20:27:09 PST 1990 + */ + +/* + * We do the conversion in C to let gcc optimize it away, if possible. + * The "fxch ; fstp" stuff is because value is still on the stack + * (stupid 8087!). + */ +double +ldexp (double value, int exp) +{ + double temp, texp, temp2; + texp = exp; +#ifdef __GNUC__ +#if __GNUC__ >= 2 + asm ("fscale " + : "=u" (temp2), "=t" (temp) + : "0" (texp), "1" (value)); +#else + asm ("fscale ; fxch %%st(1) ; fstp%L1 %1 " + : "=f" (temp), "=0" (temp2) + : "0" (texp), "f" (value)); +#endif +#else +error unknown asm +#endif + return (temp); +} diff --git a/src/kernel/libroot/posix/math/asincos.c b/src/kernel/libroot/posix/math/asincos.c new file mode 100644 index 0000000000..82664a7525 --- /dev/null +++ b/src/kernel/libroot/posix/math/asincos.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* ASIN(X) + * RETURNS ARC SINE OF X + * DOUBLE PRECISION (IEEE DOUBLE 53 bits, VAX D FORMAT 56 bits) + * CODED IN C BY K.C. NG, 4/16/85, REVISED ON 6/10/85. + * + * Required system supported functions: + * copysign(x,y) + * sqrt(x) + * + * Required kernel function: + * atan2(y,x) + * + * Method : + * asin(x) = atan2(x,sqrt(1-x*x)); for better accuracy, 1-x*x is + * computed as follows + * 1-x*x if x < 0.5, + * 2*(1-|x|)-(1-|x|)*(1-|x|) if x >= 0.5. + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN. + * + * Accuracy: + * 1) If atan2() uses machine PI, then + * + * asin(x) returns (PI/pi) * (the exact arc sine of x) nearly rounded; + * and PI is the exact pi rounded to machine precision (see atan2 for + * details): + * + * in decimal: + * pi = 3.141592653589793 23846264338327 ..... + * 53 bits PI = 3.141592653589793 115997963 ..... , + * 56 bits PI = 3.141592653589793 227020265 ..... , + * + * in hexadecimal: + * pi = 3.243F6A8885A308D313198A2E.... + * 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps + * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps + * + * In a test run with more than 200,000 random arguments on a VAX, the + * maximum observed error in ulps (units in the last place) was + * 2.06 ulps. (comparing against (PI/pi)*(exact asin(x))); + * + * 2) If atan2() uses true pi, then + * + * asin(x) returns the exact asin(x) with error below about 2 ulps. + * + * In a test run with more than 1,024,000 random arguments on a VAX, the + * maximum observed error in ulps (units in the last place) was + * 1.99 ulps. + */ + +double asin(x) +double x; +{ + double s,t,copysign(),atan2(),sqrt(),one=1.0; +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + s=copysign(x,one); + if(s <= 0.5) + return(atan2(x,sqrt(one-x*x))); + else + { t=one-s; s=t+t; return(atan2(x,sqrt(s-t*t))); } + +} + +/* ACOS(X) + * RETURNS ARC COS OF X + * DOUBLE PRECISION (IEEE DOUBLE 53 bits, VAX D FORMAT 56 bits) + * CODED IN C BY K.C. NG, 4/16/85, REVISED ON 6/10/85. + * + * Required system supported functions: + * copysign(x,y) + * sqrt(x) + * + * Required kernel function: + * atan2(y,x) + * + * Method : + * ________ + * / 1 - x + * acos(x) = 2*atan2( / -------- , 1 ) . + * \/ 1 + x + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN. + * + * Accuracy: + * 1) If atan2() uses machine PI, then + * + * acos(x) returns (PI/pi) * (the exact arc cosine of x) nearly rounded; + * and PI is the exact pi rounded to machine precision (see atan2 for + * details): + * + * in decimal: + * pi = 3.141592653589793 23846264338327 ..... + * 53 bits PI = 3.141592653589793 115997963 ..... , + * 56 bits PI = 3.141592653589793 227020265 ..... , + * + * in hexadecimal: + * pi = 3.243F6A8885A308D313198A2E.... + * 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps + * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps + * + * In a test run with more than 200,000 random arguments on a VAX, the + * maximum observed error in ulps (units in the last place) was + * 2.07 ulps. (comparing against (PI/pi)*(exact acos(x))); + * + * 2) If atan2() uses true pi, then + * + * acos(x) returns the exact acos(x) with error below about 2 ulps. + * + * In a test run with more than 1,024,000 random arguments on a VAX, the + * maximum observed error in ulps (units in the last place) was + * 2.15 ulps. + */ + +double acos(x) +double x; +{ + double t,copysign(),atan2(),sqrt(),one=1.0; +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); +#endif /* !defined(vax)&&!defined(tahoe) */ + if( x != -1.0) + t=atan2(sqrt((one-x)/(one+x)),one); + else + t=atan2(one,0.0); /* t = PI/2 */ + return(t+t); +} diff --git a/src/kernel/libroot/posix/math/asinh.c b/src/kernel/libroot/posix/math/asinh.c new file mode 100644 index 0000000000..ff0ce0b226 --- /dev/null +++ b/src/kernel/libroot/posix/math/asinh.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* ASINH(X) + * RETURN THE INVERSE HYPERBOLIC SINE OF X + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 2/16/85; + * REVISED BY K.C. NG on 3/7/85, 3/24/85, 4/16/85. + * + * Required system supported functions : + * copysign(x,y) + * sqrt(x) + * + * Required kernel function: + * log1p(x) ...return log(1+x) + * + * Method : + * Based on + * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] + * we have + * asinh(x) := x if 1+x*x=1, + * := sign(x)*(log1p(x)+ln2)) if sqrt(1+x*x)=x, else + * := sign(x)*log1p(|x| + |x|/(1/|x| + sqrt(1+(1/|x|)^2)) ) + * + * Accuracy: + * asinh(x) returns the exact inverse hyperbolic sine of x nearly rounded. + * In a test run with 52,000 random arguments on a VAX, the maximum + * observed error was 1.58 ulps (units in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ +#include "mathimpl.h" + +vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000) +vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC) + +ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000) +ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76) + +#ifdef vccast +#define ln2hi vccast(ln2hi) +#define ln2lo vccast(ln2lo) +#endif + +double +asinh(double x) +{ + double t; + double s; + static double const small = 1.0E-10; /* fl(1+small*small) == 1 */ + static double const big =1.0E20; /* fl(1+big) == big */ + static double const one =1.0; + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + if((t=copysign(x,one))>small) { + if(t big */ + {s=log1p(t)+ln2lo; return(copysign(s+ln2hi,x));} + } else { /* if |x| < small */ + return(x); + } +} diff --git a/src/kernel/libroot/posix/math/atan.c b/src/kernel/libroot/posix/math/atan.c new file mode 100644 index 0000000000..4962c0b425 --- /dev/null +++ b/src/kernel/libroot/posix/math/atan.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* ATAN(X) + * RETURNS ARC TANGENT OF X + * DOUBLE PRECISION (IEEE DOUBLE 53 bits, VAX D FORMAT 56 bits) + * CODED IN C BY K.C. NG, 4/16/85, REVISED ON 6/10/85. + * + * Required kernel function: + * atan2(y,x) + * + * Method: + * atan(x) = atan2(x,1.0). + * + * Special case: + * if x is NaN, return x itself. + * + * Accuracy: + * 1) If atan2() uses machine PI, then + * + * atan(x) returns (PI/pi) * (the exact arc tangent of x) nearly rounded; + * and PI is the exact pi rounded to machine precision (see atan2 for + * details): + * + * in decimal: + * pi = 3.141592653589793 23846264338327 ..... + * 53 bits PI = 3.141592653589793 115997963 ..... , + * 56 bits PI = 3.141592653589793 227020265 ..... , + * + * in hexadecimal: + * pi = 3.243F6A8885A308D313198A2E.... + * 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps + * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps + * + * In a test run with more than 200,000 random arguments on a VAX, the + * maximum observed error in ulps (units in the last place) was + * 0.86 ulps. (comparing against (PI/pi)*(exact atan(x))). + * + * 2) If atan2() uses true pi, then + * + * atan(x) returns the exact atan(x) with error below about 2 ulps. + * + * In a test run with more than 1,024,000 random arguments on a VAX, the + * maximum observed error in ulps (units in the last place) was + * 0.85 ulps. + */ + +double atan(x) +double x; +{ + double atan2(),one=1.0; + return(atan2(x,one)); +} diff --git a/src/kernel/libroot/posix/math/atan2.c b/src/kernel/libroot/posix/math/atan2.c new file mode 100644 index 0000000000..118517dc9f --- /dev/null +++ b/src/kernel/libroot/posix/math/atan2.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* ATAN2(Y,X) + * RETURN ARG (X+iY) + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/8/85; + * REVISED BY K.C. NG on 2/7/85, 2/13/85, 3/7/85, 3/30/85, 6/29/85. + * + * Required system supported functions : + * copysign(x,y) + * scalb(x,y) + * logb(x) + * + * Method : + * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). + * 2. Reduce x to positive by (if x and y are unexceptional): + * ARG (x+iy) = arctan(y/x) ... if x > 0, + * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, + * 3. According to the integer k=4t+0.25 truncated , t=y/x, the argument + * is further reduced to one of the following intervals and the + * arctangent of y/x is evaluated by the corresponding formula: + * + * [0,7/16] atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(y/x) = atan(1/2) + atan( (y-x/2)/(x+y/2) ) + * [11/16.19/16] atan(y/x) = atan( 1 ) + atan( (y-x)/(x+y) ) + * [19/16,39/16] atan(y/x) = atan(3/2) + atan( (y-1.5x)/(x+1.5y) ) + * [39/16,INF] atan(y/x) = atan(INF) + atan( -x/y ) + * + * Special cases: + * Notations: atan2(y,x) == ARG (x+iy) == ARG(x,y). + * + * ARG( NAN , (anything) ) is NaN; + * ARG( (anything), NaN ) is NaN; + * ARG(+(anything but NaN), +-0) is +-0 ; + * ARG(-(anything but NaN), +-0) is +-PI ; + * ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2; + * ARG( +INF,+-(anything but INF and NaN) ) is +-0 ; + * ARG( -INF,+-(anything but INF and NaN) ) is +-PI; + * ARG( +INF,+-INF ) is +-PI/4 ; + * ARG( -INF,+-INF ) is +-3PI/4; + * ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2; + * + * Accuracy: + * atan2(y,x) returns (PI/pi) * the exact ARG (x+iy) nearly rounded, + * where + * + * in decimal: + * pi = 3.141592653589793 23846264338327 ..... + * 53 bits PI = 3.141592653589793 115997963 ..... , + * 56 bits PI = 3.141592653589793 227020265 ..... , + * + * in hexadecimal: + * pi = 3.243F6A8885A308D313198A2E.... + * 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps + * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps + * + * In a test run with 356,000 random argument on [-1,1] * [-1,1] on a + * VAX, the maximum observed error was 1.41 ulps (units of the last place) + * compared with (PI/pi)*(the exact ARG(x+iy)). + * + * Note: + * We use machine PI (the true pi rounded) in place of the actual + * value of pi for all the trig and inverse trig functions. In general, + * if trig is one of sin, cos, tan, then computed trig(y) returns the + * exact trig(y*pi/PI) nearly rounded; correspondingly, computed arctrig + * returns the exact arctrig(y)*PI/pi nearly rounded. These guarantee the + * trig functions have period PI, and trig(arctrig(x)) returns x for + * all critical values x. + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(athfhi, 4.6364760900080611433E-1 ,6338,3fed,da7b,2b0d, -1, .ED63382B0DDA7B) +vc(athflo, 1.9338828231967579916E-19 ,5005,2164,92c0,9cfe, -62, .E450059CFE92C0) +vc(PIo4, 7.8539816339744830676E-1 ,0fda,4049,68c2,a221, 0, .C90FDAA22168C2) +vc(at1fhi, 9.8279372324732906796E-1 ,985e,407b,b4d9,940f, 0, .FB985E940FB4D9) +vc(at1flo,-3.5540295636764633916E-18 ,1edc,a383,eaea,34d6, -57,-.831EDC34D6EAEA) +vc(PIo2, 1.5707963267948966135E0 ,0fda,40c9,68c2,a221, 1, .C90FDAA22168C2) +vc(PI, 3.1415926535897932270E0 ,0fda,4149,68c2,a221, 2, .C90FDAA22168C2) +vc(a1, 3.3333333333333473730E-1 ,aaaa,3faa,ab75,aaaa, -1, .AAAAAAAAAAAB75) +vc(a2, -2.0000000000017730678E-1 ,cccc,bf4c,946e,cccd, -2,-.CCCCCCCCCD946E) +vc(a3, 1.4285714286694640301E-1 ,4924,3f12,4262,9274, -2, .92492492744262) +vc(a4, -1.1111111135032672795E-1 ,8e38,bee3,6292,ebc6, -3,-.E38E38EBC66292) +vc(a5, 9.0909091380563043783E-2 ,2e8b,3eba,d70c,b31b, -3, .BA2E8BB31BD70C) +vc(a6, -7.6922954286089459397E-2 ,89c8,be9d,7f18,27c3, -3,-.9D89C827C37F18) +vc(a7, 6.6663180891693915586E-2 ,86b4,3e88,9e58,ae37, -3, .8886B4AE379E58) +vc(a8, -5.8772703698290408927E-2 ,bba5,be70,a942,8481, -4,-.F0BBA58481A942) +vc(a9, 5.2170707402812969804E-2 ,b0f3,3e55,13ab,a1ab, -4, .D5B0F3A1AB13AB) +vc(a10, -4.4895863157820361210E-2 ,e4b9,be37,048f,7fd1, -4,-.B7E4B97FD1048F) +vc(a11, 3.3006147437343875094E-2 ,3174,3e07,2d87,3cf7, -4, .8731743CF72D87) +vc(a12, -1.4614844866464185439E-2 ,731a,bd6f,76d9,2f34, -6,-.EF731A2F3476D9) + +ic(athfhi, 4.6364760900080609352E-1 , -2, 1.DAC670561BB4F) +ic(athflo, 4.6249969567426939759E-18 , -58, 1.5543B8F253271) +ic(PIo4, 7.8539816339744827900E-1 , -1, 1.921FB54442D18) +ic(at1fhi, 9.8279372324732905408E-1 , -1, 1.F730BD281F69B) +ic(at1flo,-2.4407677060164810007E-17 , -56, -1.C23DFEFEAE6B5) +ic(PIo2, 1.5707963267948965580E0 , 0, 1.921FB54442D18) +ic(PI, 3.1415926535897931160E0 , 1, 1.921FB54442D18) +ic(a1, 3.3333333333333942106E-1 , -2, 1.55555555555C3) +ic(a2, -1.9999999999979536924E-1 , -3, -1.9999999997CCD) +ic(a3, 1.4285714278004377209E-1 , -3, 1.24924921EC1D7) +ic(a4, -1.1111110579344973814E-1 , -4, -1.C71C7059AF280) +ic(a5, 9.0908906105474668324E-2 , -4, 1.745CE5AA35DB2) +ic(a6, -7.6919217767468239799E-2 , -4, -1.3B0FA54BEC400) +ic(a7, 6.6614695906082474486E-2 , -4, 1.10DA924597FFF) +ic(a8, -5.8358371008508623523E-2 , -5, -1.DE125FDDBD793) +ic(a9, 4.9850617156082015213E-2 , -5, 1.9860524BDD807) +ic(a10, -3.6700606902093604877E-2 , -5, -1.2CA6C04C6937A) +ic(a11, 1.6438029044759730479E-2 , -6, 1.0D52174A1BB54) + +#ifdef vccast +#define athfhi vccast(athfhi) +#define athflo vccast(athflo) +#define PIo4 vccast(PIo4) +#define at1fhi vccast(at1fhi) +#define at1flo vccast(at1flo) +#define PIo2 vccast(PIo2) +#define PI vccast(PI) +#define a1 vccast(a1) +#define a2 vccast(a2) +#define a3 vccast(a3) +#define a4 vccast(a4) +#define a5 vccast(a5) +#define a6 vccast(a6) +#define a7 vccast(a7) +#define a8 vccast(a8) +#define a9 vccast(a9) +#define a10 vccast(a10) +#define a11 vccast(a11) +#define a12 vccast(a12) +#endif + +double +atan2(double y, double x) +{ + static const double zero=0, one=1, small=1.0E-9, big=1.0E18; + double t,z,signy,signx,hi,lo; + int k,m; + +#if !defined(vax)&&!defined(tahoe) + /* if x or y is NAN */ + if(x!=x) return(x); if(y!=y) return(y); +#endif /* !defined(vax)&&!defined(tahoe) */ + + /* copy down the sign of y and x */ + signy = copysign(one,y) ; + signx = copysign(one,x) ; + + /* if x is 1.0, goto begin */ + if(x==1) { y=copysign(y,one); t=y; if(finite(t)) goto begin;} + + /* when y = 0 */ + if(y==zero) return((signx==one)?y:copysign(PI,signy)); + + /* when x = 0 */ + if(x==zero) return(copysign(PIo2,signy)); + + /* when x is INF */ + if(!finite(x)) { + if(!finite(y)) + return(copysign((signx==one)?PIo4:3*PIo4,signy)); + else + return(copysign((signx==one)?zero:PI,signy)); + } + + /* when y is INF */ + if(!finite(y)) return(copysign(PIo2,signy)); + + /* compute y/x */ + x=copysign(x,one); + y=copysign(y,one); + if((m=(k=logb(y))-logb(x)) > 60) t=big+big; + else if(m < -80 ) t=y/x; + else { t = y/x ; y = scalb(y,-k); x=scalb(x,-k); } + + /* begin argument reduction */ +begin: + if (t < 2.4375) { + + /* truncate 4(t+1/16) to integer for branching */ + k = 4 * (t+0.0625); + switch (k) { + + /* t is in [0,7/16] */ + case 0: + case 1: + if (t < small) { + (void volatile)(big + small) ; /* raise inexact flag */ + return (copysign((signx>zero)?t:PI-t,signy)); + } + + hi = zero; lo = zero; break; + + /* t is in [7/16,11/16] */ + case 2: + hi = athfhi; lo = athflo; + z = x+x; + t = ( (y+y) - x ) / ( z + y ); break; + + /* t is in [11/16,19/16] */ + case 3: + case 4: + hi = PIo4; lo = zero; + t = ( y - x ) / ( x + y ); break; + + /* t is in [19/16,39/16] */ + default: + hi = at1fhi; lo = at1flo; + z = y-x; y=y+y+y; t = x+x; + t = ( (z+z)-x ) / ( t + y ); break; + } + } + /* end of if (t < 2.4375) */ + + else + { + hi = PIo2; lo = zero; + + /* t is in [2.4375, big] */ + if (t <= big) { + t = - x / y; + } else { + /* t is in [big, INF] */ + (void volatile)(big+small); /* raise inexact flag */ + t = zero; + } + } + /* end of argument reduction */ + + /* compute atan(t) for t in [-.4375, .4375] */ + z = t*t; +#if defined(vax)||defined(tahoe) + z = t*(z*(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*(a6+z*(a7+z*(a8+ + z*(a9+z*(a10+z*(a11+z*a12)))))))))))); +#else /* defined(vax)||defined(tahoe) */ + z = t*(z*(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*(a6+z*(a7+z*(a8+ + z*(a9+z*(a10+z*a11))))))))))); +#endif /* defined(vax)||defined(tahoe) */ + z = lo - z; z += t; z += hi; + + return(copysign((signx>zero)?z:PI-z,signy)); +} diff --git a/src/kernel/libroot/posix/math/atanh.c b/src/kernel/libroot/posix/math/atanh.c new file mode 100644 index 0000000000..e1f98432c8 --- /dev/null +++ b/src/kernel/libroot/posix/math/atanh.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* ATANH(X) + * RETURN THE HYPERBOLIC ARC TANGENT OF X + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/8/85; + * REVISED BY K.C. NG on 2/7/85, 3/7/85, 8/18/85. + * + * Required kernel function: + * log1p(x) ...return log(1+x) + * + * Method : + * Return + * 1 2x x + * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) + * 2 1 - x 1 - x + * + * Special cases: + * atanh(x) is NaN if |x| > 1 with signal; + * atanh(NaN) is that NaN with no signal; + * atanh(+-1) is +-INF with signal. + * + * Accuracy: + * atanh(x) returns the exact hyperbolic arc tangent of x nearly rounded. + * In a test run with 512,000 random arguments on a VAX, the maximum + * observed error was 1.87 ulps (units in the last place) at + * x= -3.8962076028810414000e-03. + */ +#include "mathimpl.h" + +#if defined(vax)||defined(tahoe) +#include +#endif /* defined(vax)||defined(tahoe) */ + +double atanh(x) +double x; +{ + double z; + z = copysign(0.5,x); + x = copysign(x,1.0); +#if defined(vax)||defined(tahoe) + if (x == 1.0) { + return(copysign(1.0,z)*infnan(ERANGE)); /* sign(x)*INF */ + } +#endif /* defined(vax)||defined(tahoe) */ + x = x/(1.0-x); + return( z*log1p(x+x) ); +} diff --git a/src/kernel/libroot/posix/math/cabs.c b/src/kernel/libroot/posix/math/cabs.c new file mode 100644 index 0000000000..8f3e59ac31 --- /dev/null +++ b/src/kernel/libroot/posix/math/cabs.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* HYPOT(X,Y) + * RETURN THE SQUARE ROOT OF X^2 + Y^2 WHERE Z=X+iY + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 11/28/84; + * REVISED BY K.C. NG, 7/12/85. + * + * Required system supported functions : + * copysign(x,y) + * finite(x) + * scalb(x,N) + * sqrt(x) + * + * Method : + * 1. replace x by |x| and y by |y|, and swap x and + * y if y > x (hence x is never smaller than y). + * 2. Hypot(x,y) is computed by: + * Case I, x/y > 2 + * + * y + * hypot = x + ----------------------------- + * 2 + * sqrt ( 1 + [x/y] ) + x/y + * + * Case II, x/y <= 2 + * y + * hypot = x + -------------------------------------------------- + * 2 + * [x/y] - 2 + * (sqrt(2)+1) + (x-y)/y + ----------------------------- + * 2 + * sqrt ( 1 + [x/y] ) + sqrt(2) + * + * + * + * Special cases: + * hypot(x,y) is INF if x or y is +INF or -INF; else + * hypot(x,y) is NAN if x or y is NAN. + * + * Accuracy: + * hypot(x,y) returns the sqrt(x^2+y^2) with error less than 1 ulps (units + * in the last place). See Kahan's "Interval Arithmetic Options in the + * Proposed IEEE Floating Point Arithmetic Standard", Interval Mathematics + * 1980, Edited by Karl L.E. Nickel, pp 99-128. (A faster but less accurate + * code follows in comments.) In a test run with 500,000 random arguments + * on a VAX, the maximum observed error was .959 ulps. + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ +#include "mathimpl.h" + +vc(r2p1hi, 2.4142135623730950345E0 ,8279,411a,ef32,99fc, 2, .9A827999FCEF32) +vc(r2p1lo, 1.4349369327986523769E-17 ,597d,2484,754b,89b3, -55, .84597D89B3754B) +vc(sqrt2, 1.4142135623730950622E0 ,04f3,40b5,de65,33f9, 1, .B504F333F9DE65) + +ic(r2p1hi, 2.4142135623730949234E0 , 1, 1.3504F333F9DE6) +ic(r2p1lo, 1.2537167179050217666E-16 , -53, 1.21165F626CDD5) +ic(sqrt2, 1.4142135623730951455E0 , 0, 1.6A09E667F3BCD) + +#ifdef vccast +#define r2p1hi vccast(r2p1hi) +#define r2p1lo vccast(r2p1lo) +#define sqrt2 vccast(sqrt2) +#endif + +double +hypot(double x, double y) +{ + static double const zero=0; + static double const one=1; + static double const small=1.0E-18; /* fl(1+small)==1 */ + static int const ibig=30; /* fl(1+2**(2*ibig))==1 */ + double t; + double r; + int exp; + + if(finite(x)) { + if(finite(y)) { + x=copysign(x,one); + y=copysign(y,one); + if(y > x) { + t=x; x=y; y=t; + } + if(x == zero) return(zero); + if(y == zero) return(x); + exp= logb(x); + if(exp-(int)logb(y) > ibig ) { + /* raise inexact flag and return |x| */ + (void volatile)(one+small); + return(x); + } + + /* start computing sqrt(x^2 + y^2) */ + r=x-y; + if(r>y) { /* x/y > 2 */ + r=x/y; + r=r+sqrt(one+r*r); + } else { /* 1 <= x/y <= 2 */ + r/=y; t=r*(r+2.0); + r+=t/(sqrt2+sqrt(2.0+t)); + r+=r2p1lo; r+=r2p1hi; + } + + r=y/r; + return(x+r); + + } + + else if(y==y) /* y is +-INF */ + return(copysign(y,one)); + else + return(y); /* y is NaN and x is finite */ + + } else if(x==x) { + return (copysign(x,one)); /* x is +-INF */ + } else if(finite(y)) { + return(x); /* x is NaN, y is finite */ +#if !defined(vax)&&!defined(tahoe) + } else if(y!=y) { + return(y); /* x and y is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + } else { + return(copysign(y,one)); /* y is INF */ + } +} + +/* CABS(Z) + * RETURN THE ABSOLUTE VALUE OF THE COMPLEX NUMBER Z = X + iY + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 11/28/84. + * REVISED BY K.C. NG, 7/12/85. + * + * Required kernel function : + * hypot(x,y) + * + * Method : + * cabs(z) = hypot(x,y) . + */ + +double +cabs(struct complex z) +{ + return hypot(z.x,z.y); +} + +double +z_abs(struct complex const *z) +{ + return hypot(z->x,z->y); +} + +/* A faster but less accurate version of cabs(x,y) */ +#if 0 +double hypot(x,y) +double x, y; +{ + static const double zero=0, one=1; + small=1.0E-18; /* fl(1+small)==1 */ + static const ibig=30; /* fl(1+2**(2*ibig))==1 */ + double temp; + int exp; + + if(finite(x)) + if(finite(y)) + { + x=copysign(x,one); + y=copysign(y,one); + if(y > x) + { temp=x; x=y; y=temp; } + if(x == zero) return(zero); + if(y == zero) return(x); + exp= logb(x); + x=scalb(x,-exp); + if(exp-(int)logb(y) > ibig ) + /* raise inexact flag and return |x| */ + { one+small; return(scalb(x,exp)); } + else y=scalb(y,-exp); + return(scalb(sqrt(x*x+y*y),exp)); + } + + else if(y==y) /* y is +-INF */ + return(copysign(y,one)); + else + return(y); /* y is NaN and x is finite */ + + else if(x==x) /* x is +-INF */ + return (copysign(x,one)); + else if(finite(y)) + return(x); /* x is NaN, y is finite */ + else if(y!=y) return(y); /* x and y is NaN */ + else return(copysign(y,one)); /* y is INF */ +} +#endif diff --git a/src/kernel/libroot/posix/math/cbrt.c b/src/kernel/libroot/posix/math/cbrt.c new file mode 100644 index 0000000000..13ee6d74f4 --- /dev/null +++ b/src/kernel/libroot/posix/math/cbrt.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +/* kahan's cube root (53 bits IEEE double precision) + * for IEEE machines only + * coded in C by K.C. Ng, 4/30/85 + * + * Accuracy: + * better than 0.667 ulps according to an error analysis. Maximum + * error observed was 0.666 ulps in an 1,000,000 random arguments test. + * + * Warning: this code is semi machine dependent; the ordering of words in + * a floating point number must be known in advance. I assume that the + * long interger at the address of a floating point number will be the + * leading 32 bits of that floating point number (i.e., sign, exponent, + * and the 20 most significant bits). + * On a National machine, it has different ordering; therefore, this code + * must be compiled with flag -DNATIONAL. + */ +#if !defined(vax)&&!defined(tahoe) + +static unsigned long const B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */ +static unsigned long const B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ +static double const C= 19./35.; +static double const D= -864./1225.; +static double const E= 99./70.; +static double const F= 45./28.; +static double const G= 5./14.; + +double +cbrt(double x) +{ + double r; + double s; + double t=0.0; + double w; + unsigned long *px = (unsigned long *) &x; + unsigned long *pt = (unsigned long *) &t; + unsigned long mexp; + unsigned long sign; + +#ifdef national /* ordering of words in a floating points number */ + const int n0=1; + const int n1=0; +#else /* national */ + const int n0=0; + const int n1=1; +#endif /* national */ + + mexp=px[n0]&0x7ff00000; + if(mexp==0x7ff00000) return(x); /* cbrt(NaN,INF) is itself */ + if(x==0.0) return(x); /* cbrt(0) is itself */ + + sign=px[n0]&0x80000000; /* sign= sign(x) */ + px[n0] ^= sign; /* x=|x| */ + + + /* rough cbrt to 5 bits */ + if(mexp==0) { + /* subnormal number */ + pt[n0]=0x43500000; /* set t= 2**54 */ + t*=x; + pt[n0]=pt[n0]/3+B2; + } else { + pt[n0]=px[n0]/3+B1; + } + + + /* new cbrt to 23 bits, may be implemented in single precision */ + r=t*t/x; + s=C+r*t; + t*=G+F/(s+E+D/s); + + /* chopped to 20 bits and make it larger than cbrt(x) */ + pt[n1]=0; pt[n0]+=0x00000001; + + + /* one step newton iteration to 53 bits with error less than 0.667 ulps */ + s=t*t; /* t*t is exact */ + r=x/s; + w=t+t; + r=(r-t)/(w+r); /* r-t is exact */ + t=t+t*r; + + + /* retore the sign bit */ + pt[n0] |= sign; + return(t); +} +#endif diff --git a/src/kernel/libroot/posix/math/cosh.c b/src/kernel/libroot/posix/math/cosh.c new file mode 100644 index 0000000000..296b63c0f8 --- /dev/null +++ b/src/kernel/libroot/posix/math/cosh.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* COSH(X) + * RETURN THE HYPERBOLIC COSINE OF X + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/8/85; + * REVISED BY K.C. NG on 2/8/85, 2/23/85, 3/7/85, 3/29/85, 4/16/85. + * + * Required system supported functions : + * copysign(x,y) + * scalb(x,N) + * + * Required kernel function: + * exp(x) + * exp__E(x,c) ...return exp(x+c)-1-x for |x|<0.3465 + * + * Method : + * 1. Replace x by |x|. + * 2. + * [ exp(x) - 1 ]^2 + * 0 <= x <= 0.3465 : cosh(x) := 1 + ------------------- + * 2*exp(x) + * + * exp(x) + 1/exp(x) + * 0.3465 <= x <= 22 : cosh(x) := ------------------- + * 2 + * 22 <= x <= lnovfl : cosh(x) := exp(x)/2 + * lnovfl <= x <= lnovfl+log(2) + * : cosh(x) := exp(x)/2 (avoid overflow) + * log(2)+lnovfl < x < INF: overflow to INF + * + * Note: .3465 is a number near one half of ln2. + * + * Special cases: + * cosh(x) is x if x is +INF, -INF, or NaN. + * only cosh(0)=1 is exact for finite x. + * + * Accuracy: + * cosh(x) returns the exact hyperbolic cosine of x nearly rounded. + * In a test run with 768,000 random arguments on a VAX, the maximum + * observed error was 1.23 ulps (units in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(mln2hi, 8.8029691931113054792E1 ,0f33,43b0,2bdb,c7e2, 7, .B00F33C7E22BDB) +vc(mln2lo,-4.9650192275318476525E-16 ,1b60,a70f,582a,279e, -50,-.8F1B60279E582A) +vc(lnovfl, 8.8029691931113053016E1 ,0f33,43b0,2bda,c7e2, 7, .B00F33C7E22BDA) + +ic(mln2hi, 7.0978271289338397310E2, 10, 1.62E42FEFA39EF) +ic(mln2lo, 2.3747039373786107478E-14, -45, 1.ABC9E3B39803F) +ic(lnovfl, 7.0978271289338397310E2, 9, 1.62E42FEFA39EF) + +#ifdef vccast +#define mln2hi vccast(mln2hi) +#define mln2lo vccast(mln2lo) +#define lnovfl vccast(lnovfl) +#endif + +#if defined(vax)||defined(tahoe) +static int const max = 126 ; +#else /* defined(vax)||defined(tahoe) */ +static int const max = 1023 ; +#endif /* defined(vax)||defined(tahoe) */ + +double +cosh(double x) +{ + static double const half=1.0/2.0; + static double const one=1.0; + static double const small=1.0E-18; /* fl(1+small)==1 */ + double t; + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + if((x=copysign(x,one)) <= 22) { + if(x<0.3465) + if(x= 1.25 (error 1.7ulp vs ~6ulp) + * Replaced even+odd with direct calculation for x < .84375, + * to avoid destructive cancellation. + * + * Performance of erfc(x): + * In 300000 trials in the range [.83, .84375] the + * maximum observed error was 3.6ulp. + * + * In [.84735,1.25] the maximum observed error was <2.5ulp in + * 100000 runs in the range [1.2, 1.25]. + * + * In [1.25,26] (Not including subnormal results) + * the error is < 1.7ulp. + */ + +/* double erf(double x) + * double erfc(double x) + * x + * 2 |\ + * erf(x) = --------- | exp(-t*t)dt + * sqrt(pi) \| + * 0 + * + * erfc(x) = 1-erf(x) + * + * Method: + * 1. Reduce x to |x| by erf(-x) = -erf(x) + * 2. For x in [0, 0.84375] + * erf(x) = x + x*P(x^2) + * erfc(x) = 1 - erf(x) if x<=0.25 + * = 0.5 + ((0.5-x)-x*P) if x in [0.25,0.84375] + * where + * 2 2 4 20 + * P = P(x ) = (p0 + p1 * x + p2 * x + ... + p10 * x ) + * is an approximation to (erf(x)-x)/x with precision + * + * -56.45 + * | P - (erf(x)-x)/x | <= 2 + * + * + * Remark. The formula is derived by noting + * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) + * and that + * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 + * is close to one. The interval is chosen because the fixed + * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is + * near 0.6174), and by some experiment, 0.84375 is chosen to + * guarantee the error is less than one ulp for erf. + * + * 3. For x in [0.84375,1.25], let s = x - 1, and + * c = 0.84506291151 rounded to single (24 bits) + * erf(x) = c + P1(s)/Q1(s) + * erfc(x) = (1-c) - P1(s)/Q1(s) + * |P1/Q1 - (erf(x)-c)| <= 2**-59.06 + * Remark: here we use the taylor series expansion at x=1. + * erf(1+s) = erf(1) + s*Poly(s) + * = 0.845.. + P1(s)/Q1(s) + * That is, we use rational approximation to approximate + * erf(1+s) - (c = (single)0.84506291151) + * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] + * where + * P1(s) = degree 6 poly in s + * Q1(s) = degree 6 poly in s + * + * 4. For x in [1.25, 2]; [2, 4] + * erf(x) = 1.0 - tiny + * erfc(x) = (1/x)exp(-x*x-(.5*log(pi) -.5z + R(z)/S(z)) + * + * Where z = 1/(x*x), R is degree 9, and S is degree 3; + * + * 5. For x in [4,28] + * erf(x) = 1.0 - tiny + * erfc(x) = (1/x)exp(-x*x-(.5*log(pi)+eps + zP(z)) + * + * Where P is degree 14 polynomial in 1/(x*x). + * + * Notes: + * Here 4 and 5 make use of the asymptotic series + * exp(-x*x) + * erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) ); + * x*sqrt(pi) + * + * where for z = 1/(x*x) + * P(z) ~ z/2*(-1 + z*3/2*(1 + z*5/2*(-1 + z*7/2*(1 +...)))) + * + * Thus we use rational approximation to approximate + * erfc*x*exp(x*x) ~ 1/sqrt(pi); + * + * The error bound for the target function, G(z) for + * the interval + * [4, 28]: + * |eps + 1/(z)P(z) - G(z)| < 2**(-56.61) + * for [2, 4]: + * |R(z)/S(z) - G(z)| < 2**(-58.24) + * for [1.25, 2]: + * |R(z)/S(z) - G(z)| < 2**(-58.12) + * + * 6. For inf > x >= 28 + * erf(x) = 1 - tiny (raise inexact) + * erfc(x) = tiny*tiny (raise underflow) + * + * 7. Special cases: + * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, + * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, + * erfc/erf(NaN) is NaN + */ + +#include +#include "mathimpl.h" + +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +#define TRUNC(x) (double) (float) (x) +#else +#define _IEEE 1 +#define TRUNC(x) *(((int *) &x) + 1) &= 0xf8000000 +#define infnan(x) 0.0 +#endif + +#ifdef _IEEE_LIBM +/* + * redefining "___function" to "function" in _IEEE_LIBM mode + */ +#include "ieee_libm.h" +#endif + +static double const tiny = 1e-300; +static double const half = 0.5; +static double const one = 1.0; +static double const two = 2.0; +static double const c = 8.45062911510467529297e-01; /* (float)0.84506291151 */ +/* + * Coefficients for approximation to erf in [0,0.84375] + */ +static double const p0t8 = 1.02703333676410051049867154944018394163280; +static double const p0 = 1.283791670955125638123339436800229927041e-0001; +static double const p1 = -3.761263890318340796574473028946097022260e-0001; +static double const p2 = 1.128379167093567004871858633779992337238e-0001; +static double const p3 = -2.686617064084433642889526516177508374437e-0002; +static double const p4 = 5.223977576966219409445780927846432273191e-0003; +static double const p5 = -8.548323822001639515038738961618255438422e-0004; +static double const p6 = 1.205520092530505090384383082516403772317e-0004; +static double const p7 = -1.492214100762529635365672665955239554276e-0005; +static double const p8 = 1.640186161764254363152286358441771740838e-0006; +static double const p9 = -1.571599331700515057841960987689515895479e-0007; +static double const p10= 1.073087585213621540635426191486561494058e-0008; +/* + * Coefficients for approximation to erf in [0.84375,1.25] + */ +static double const pa0 = -2.362118560752659485957248365514511540287e-0003; +static double const pa1 = 4.148561186837483359654781492060070469522e-0001; +static double const pa2 = -3.722078760357013107593507594535478633044e-0001; +static double const pa3 = 3.183466199011617316853636418691420262160e-0001; +static double const pa4 = -1.108946942823966771253985510891237782544e-0001; +static double const pa5 = 3.547830432561823343969797140537411825179e-0002; +static double const pa6 = -2.166375594868790886906539848893221184820e-0003; +static double const qa1 = 1.064208804008442270765369280952419863524e-0001; +static double const qa2 = 5.403979177021710663441167681878575087235e-0001; +static double const qa3 = 7.182865441419627066207655332170665812023e-0002; +static double const qa4 = 1.261712198087616469108438860983447773726e-0001; +static double const qa5 = 1.363708391202905087876983523620537833157e-0002; +static double const qa6 = 1.198449984679910764099772682882189711364e-0002; +/* + * log(sqrt(pi)) for large x expansions. + * The tail (lsqrtPI_lo) is included in the rational + * approximations. +*/ +static double const lsqrtPI_hi = .5723649429247000819387380943226; +/* + * lsqrtPI_lo = .000000000000000005132975581353913; + * + * Coefficients for approximation to erfc in [2, 4] +*/ +static double const rb0 = -1.5306508387410807582e-010; /* includes lsqrtPI_lo */ +static double const rb1 = 2.15592846101742183841910806188e-008; +static double const rb2 = 6.24998557732436510470108714799e-001; +static double const rb3 = 8.24849222231141787631258921465e+000; +static double const rb4 = 2.63974967372233173534823436057e+001; +static double const rb5 = 9.86383092541570505318304640241e+000; +static double const rb6 = -7.28024154841991322228977878694e+000; +static double const rb7 = 5.96303287280680116566600190708e+000; +static double const rb8 = -4.40070358507372993983608466806e+000; +static double const rb9 = 2.39923700182518073731330332521e+000; +static double const rb10 = -6.89257464785841156285073338950e-001; +static double const sb1 = 1.56641558965626774835300238919e+001; +static double const sb2 = 7.20522741000949622502957936376e+001; +static double const sb3 = 9.60121069770492994166488642804e+001; +/* + * Coefficients for approximation to erfc in [1.25, 2] +*/ +static double const rc0 = -2.47925334685189288817e-007; /* includes lsqrtPI_lo */ +static double const rc1 = 1.28735722546372485255126993930e-005; +static double const rc2 = 6.24664954087883916855616917019e-001; +static double const rc3 = 4.69798884785807402408863708843e+000; +static double const rc4 = 7.61618295853929705430118701770e+000; +static double const rc5 = 9.15640208659364240872946538730e-001; +static double const rc6 = -3.59753040425048631334448145935e-001; +static double const rc7 = 1.42862267989304403403849619281e-001; +static double const rc8 = -4.74392758811439801958087514322e-002; +static double const rc9 = 1.09964787987580810135757047874e-002; +static double const rc10 = -1.28856240494889325194638463046e-003; +static double const sc1 = 9.97395106984001955652274773456e+000; +static double const sc2 = 2.80952153365721279953959310660e+001; +static double const sc3 = 2.19826478142545234106819407316e+001; +/* + * Coefficients for approximation to erfc in [4,28] + */ +static double const rd0 = -2.1491361969012978677e-016; /* includes lsqrtPI_lo */ +static double const rd1 = -4.99999999999640086151350330820e-001; +static double const rd2 = 6.24999999772906433825880867516e-001; +static double const rd3 = -1.54166659428052432723177389562e+000; +static double const rd4 = 5.51561147405411844601985649206e+000; +static double const rd5 = -2.55046307982949826964613748714e+001; +static double const rd6 = 1.43631424382843846387913799845e+002; +static double const rd7 = -9.45789244999420134263345971704e+002; +static double const rd8 = 6.94834146607051206956384703517e+003; +static double const rd9 = -5.27176414235983393155038356781e+004; +static double const rd10 = 3.68530281128672766499221324921e+005; +static double const rd11 = -2.06466642800404317677021026611e+006; +static double const rd12 = 7.78293889471135381609201431274e+006; +static double const rd13 = -1.42821001129434127360582351685e+007; + +double +erf(double x) +{ + double R; + double S; + double P; + double Q; + double ax; + double s; + double y; + double z; + double r; + + if(!finite(x)) { /* erf(nan)=nan */ + if (isnan(x)) + return(x); + return (x > 0 ? one : -one); /* erf(+/-inf)= +/-1 */ + } + if ((ax = x) < 0) + ax = - ax; + if (ax < .84375) { + if (ax < 3.7e-09) { + if (ax < 1.0e-308) + return 0.125*(8.0*x+p0t8*x); /*avoid underflow */ + return x + p0*x; + } + y = x*x; + r = y*(p1+y*(p2+y*(p3+y*(p4+y*(p5+ + y*(p6+y*(p7+y*(p8+y*(p9+y*p10))))))))); + return x + x*(p0+r); + } + if (ax < 1.25) { /* 0.84375 <= |x| < 1.25 */ + s = fabs(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if (x>=0) + return (c + P/Q); + else + return (-c - P/Q); + } + if (ax >= 6.0) { /* inf>|x|>=6 */ + if (x >= 0.0) + return (one-tiny); + else + return (tiny-one); + } + /* 1.25 <= |x| < 6 */ + z = -ax*ax; + s = -one/z; + if (ax < 2.0) { + R = rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+ + s*(rc6+s*(rc7+s*(rc8+s*(rc9+s*rc10))))))))); + S = one+s*(sc1+s*(sc2+s*sc3)); + } else { + R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+ + s*(rb6+s*(rb7+s*(rb8+s*(rb9+s*rb10))))))))); + S = one+s*(sb1+s*(sb2+s*sb3)); + } + y = (R/S -.5*s) - lsqrtPI_hi; + z += y; + z = exp(z)/ax; + if (x >= 0) + return (one-z); + else + return (z-one); +} + +double +erfc(double x) +{ + double R; + double S; + double P; + double Q; + double s; + double ax; + double y; + double z; + double r; + + if (!finite(x)) { + if (isnan(x)) /* erfc(NaN) = NaN */ + return(x); + else if (x > 0) /* erfc(+-inf)=0,2 */ + return 0.0; + else + return 2.0; + } + if ((ax = x) < 0) + ax = -ax; + if (ax < .84375) { /* |x|<0.84375 */ + if (ax < 1.38777878078144568e-17) /* |x|<2**-56 */ + return one-x; + y = x*x; + r = y*(p1+y*(p2+y*(p3+y*(p4+y*(p5+ + y*(p6+y*(p7+y*(p8+y*(p9+y*p10))))))))); + if (ax < .0625) { /* |x|<2**-4 */ + return (one-(x+x*(p0+r))); + } else { + r = x*(p0+r); + r += (x-half); + return (half - r); + } + } + if (ax < 1.25) { /* 0.84375 <= |x| < 1.25 */ + s = ax-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if (x>=0) { + z = one-c; return z - P/Q; + } else { + z = c+P/Q; return one+z; + } + } + if (ax >= 28) { /* Out of range */ + if (x>0) + return (tiny*tiny); + else + return (two-tiny); + } + z = ax; + TRUNC(z); + y = z - ax; y *= (ax+z); + z *= -z; /* Here z + y = -x^2 */ + s = one/(-z-y); /* 1/(x*x) */ + if (ax >= 4) { /* 6 <= ax */ + R = s*(rd1+s*(rd2+s*(rd3+s*(rd4+s*(rd5+ + s*(rd6+s*(rd7+s*(rd8+s*(rd9+s*(rd10 + +s*(rd11+s*(rd12+s*rd13)))))))))))); + y += rd0; + } else if (ax >= 2) { + R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+ + s*(rb6+s*(rb7+s*(rb8+s*(rb9+s*rb10))))))))); + S = one+s*(sb1+s*(sb2+s*sb3)); + y += R/S; + R = -.5*s; + } else { + R = rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+ + s*(rc6+s*(rc7+s*(rc8+s*(rc9+s*rc10))))))))); + S = one+s*(sc1+s*(sc2+s*sc3)); + y += R/S; + R = -.5*s; + } + /* return exp(-x^2 - lsqrtPI_hi + R + y)/x; */ + s = ((R + y) - lsqrtPI_hi) + z; + y = (((z-s) - lsqrtPI_hi) + R) + y; + r = __exp__D(s, y)/x; + if (x>0) + return r; + else + return two-r; +} diff --git a/src/kernel/libroot/posix/math/exp.c b/src/kernel/libroot/posix/math/exp.c new file mode 100644 index 0000000000..dd8ff433b4 --- /dev/null +++ b/src/kernel/libroot/posix/math/exp.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* EXP(X) + * RETURN THE EXPONENTIAL OF X + * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS) + * CODED IN C BY K.C. NG, 1/19/85; + * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86. + * + * Required system supported functions: + * scalb(x,n) + * copysign(x,y) + * finite(x) + * + * Method: + * 1. Argument Reduction: given the input x, find r and integer k such + * that + * x = k*ln2 + r, |r| <= 0.5*ln2 . + * r will be represented as r := z+c for better accuracy. + * + * 2. Compute exp(r) by + * + * exp(r) = 1 + r + r*R1/(2-R1), + * where + * R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))). + * + * 3. exp(x) = 2^k * exp(r) . + * + * Special cases: + * exp(INF) is INF, exp(NaN) is NaN; + * exp(-INF)= 0; + * for finite argument, only exp(0)=1 is exact. + * + * Accuracy: + * exp(x) returns the exponential of x nearly rounded. In a test run + * with 1,156,000 random arguments on a VAX, the maximum observed + * error was 0.869 ulps (units in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000) +vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC) +vc(lnhuge, 9.4961163736712506989E1 ,ec1d,43bd,9010,a73e, 7, .BDEC1DA73E9010) +vc(lntiny,-9.5654310917272452386E1 ,4f01,c3bf,33af,d72e, 7,-.BF4F01D72E33AF) +vc(invln2, 1.4426950408889634148E0 ,aa3b,40b8,17f1,295c, 1, .B8AA3B295C17F1) +vc(p1, 1.6666666666666602251E-1 ,aaaa,3f2a,a9f1,aaaa, -2, .AAAAAAAAAAA9F1) +vc(p2, -2.7777777777015591216E-3 ,0b60,bc36,ec94,b5f5, -8,-.B60B60B5F5EC94) +vc(p3, 6.6137563214379341918E-5 ,b355,398a,f15f,792e, -13, .8AB355792EF15F) +vc(p4, -1.6533902205465250480E-6 ,ea0e,b6dd,5f84,2e93, -19,-.DDEA0E2E935F84) +vc(p5, 4.1381367970572387085E-8 ,bb4b,3431,2683,95f5, -24, .B1BB4B95F52683) + +#ifdef vccast +#define ln2hi vccast(ln2hi) +#define ln2lo vccast(ln2lo) +#define lnhuge vccast(lnhuge) +#define lntiny vccast(lntiny) +#define invln2 vccast(invln2) +#define p1 vccast(p1) +#define p2 vccast(p2) +#define p3 vccast(p3) +#define p4 vccast(p4) +#define p5 vccast(p5) +#endif + +ic(p1, 1.6666666666666601904E-1, -3, 1.555555555553E) +ic(p2, -2.7777777777015593384E-3, -9, -1.6C16C16BEBD93) +ic(p3, 6.6137563214379343612E-5, -14, 1.1566AAF25DE2C) +ic(p4, -1.6533902205465251539E-6, -20, -1.BBD41C5D26BF1) +ic(p5, 4.1381367970572384604E-8, -25, 1.6376972BEA4D0) +ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000) +ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76) +ic(lnhuge, 7.1602103751842355450E2, 9, 1.6602B15B7ECF2) +ic(lntiny,-7.5137154372698068983E2, 9, -1.77AF8EBEAE354) +ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE) + +double exp(x) +double x; +{ + double z,hi,lo,c; + int k; + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + if( x <= lnhuge ) { + if( x >= lntiny ) { + + /* argument reduction : x --> x - k*ln2 */ + + k=invln2*x+copysign(0.5,x); /* k=NINT(x/ln2) */ + + /* express x-k*ln2 as hi-lo and let x=hi-lo rounded */ + + hi=x-k*ln2hi; + x=hi-(lo=k*ln2lo); + + /* return 2^k*[1+x+x*c/(2+c)] */ + z=x*x; + c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5)))); + return scalb(1.0+(hi-(lo-(x*c)/(2.0-c))),k); + + } + /* end of x > lntiny */ + + else + /* exp(-big#) underflows to zero */ + if(finite(x)) return(scalb(1.0,-5000)); + + /* exp(-INF) is zero */ + else return(0.0); + } + /* end of x < lnhuge */ + + else + /* exp(INF) is INF, exp(+big#) overflows to INF */ + return( finite(x) ? scalb(1.0,5000) : x); +} + +/* returns exp(r = x + c) for |c| < |x| with no overlap. */ + +double __exp__D(x, c) +double x, c; +{ + double z,hi,lo; + int k; + +#if !defined(vax)&&!defined(tahoe) + if (x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + if ( x <= lnhuge ) { + if ( x >= lntiny ) { + + /* argument reduction : x --> x - k*ln2 */ + z = invln2*x; + k = z + copysign(.5, x); + + /* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */ + + hi=(x-k*ln2hi); /* Exact. */ + x= hi - (lo = k*ln2lo-c); + /* return 2^k*[1+x+x*c/(2+c)] */ + z=x*x; + c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5)))); + c = (x*c)/(2.0-c); + + return scalb(1.+(hi-(lo - c)), k); + } + /* end of x > lntiny */ + + else + /* exp(-big#) underflows to zero */ + if(finite(x)) return(scalb(1.0,-5000)); + + /* exp(-INF) is zero */ + else return(0.0); + } + /* end of x < lnhuge */ + + else + /* exp(INF) is INF, exp(+big#) overflows to INF */ + return( finite(x) ? scalb(1.0,5000) : x); +} diff --git a/src/kernel/libroot/posix/math/exp__E.c b/src/kernel/libroot/posix/math/exp__E.c new file mode 100644 index 0000000000..4369e6b283 --- /dev/null +++ b/src/kernel/libroot/posix/math/exp__E.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* exp__E(x,c) + * ASSUMPTION: c << x SO THAT fl(x+c)=x. + * (c is the correction term for x) + * exp__E RETURNS + * + * / exp(x+c) - 1 - x , 1E-19 < |x| < .3465736 + * exp__E(x,c) = | + * \ 0 , |x| < 1E-19. + * + * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS) + * KERNEL FUNCTION OF EXP, EXPM1, POW FUNCTIONS + * CODED IN C BY K.C. NG, 1/31/85; + * REVISED BY K.C. NG on 3/16/85, 4/16/85. + * + * Required system supported function: + * copysign(x,y) + * + * Method: + * 1. Rational approximation. Let r=x+c. + * Based on + * 2 * sinh(r/2) + * exp(r) - 1 = ---------------------- , + * cosh(r/2) - sinh(r/2) + * exp__E(r) is computed using + * x*x (x/2)*W - ( Q - ( 2*P + x*P ) ) + * --- + (c + x*[---------------------------------- + c ]) + * 2 1 - W + * where P := p1*x^2 + p2*x^4, + * Q := q1*x^2 + q2*x^4 (for 56 bits precision, add q3*x^6) + * W := x/2-(Q-x*P), + * + * (See the listing below for the values of p1,p2,q1,q2,q3. The poly- + * nomials P and Q may be regarded as the approximations to sinh + * and cosh : + * sinh(r/2) = r/2 + r * P , cosh(r/2) = 1 + Q . ) + * + * The coefficients were obtained by a special Remez algorithm. + * + * Approximation error: + * + * | exp(x) - 1 | 2**(-57), (IEEE double) + * | ------------ - (exp__E(x,0)+x)/x | <= + * | x | 2**(-69). (VAX D) + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(p1, 1.5150724356786683059E-2 ,3abe,3d78,066a,67e1, -6, .F83ABE67E1066A) +vc(p2, 6.3112487873718332688E-5 ,5b42,3984,0173,48cd, -13, .845B4248CD0173) +vc(q1, 1.1363478204690669916E-1 ,b95a,3ee8,ec45,44a2, -3, .E8B95A44A2EC45) +vc(q2, 1.2624568129896839182E-3 ,7905,3ba5,f5e7,72e4, -9, .A5790572E4F5E7) +vc(q3, 1.5021856115869022674E-6 ,9eb4,36c9,c395,604a, -19, .C99EB4604AC395) + +ic(p1, 1.3887401997267371720E-2, -7, 1.C70FF8B3CC2CF) +ic(p2, 3.3044019718331897649E-5, -15, 1.15317DF4526C4) +ic(q1, 1.1110813732786649355E-1, -4, 1.C719538248597) +ic(q2, 9.9176615021572857300E-4, -10, 1.03FC4CB8C98E8) + +#ifdef vccast +#define p1 vccast(p1) +#define p2 vccast(p2) +#define q1 vccast(q1) +#define q2 vccast(q2) +#define q3 vccast(q3) +#endif + +double +__exp__E(double x, double c) +{ + static double const zero=0.0; + static double const one=1.0; + static double const half=1.0/2.0; + static double const small=1.0E-19; + double z; + double p; + double q; + double xp; + double xh; + double w; + + if(copysign(x,one)>small) { + z = x*x ; + p = z*( p1 +z* p2 ); +#if defined(vax)||defined(tahoe) + q = z*( q1 +z*( q2 +z* q3 )); +#else /* defined(vax)||defined(tahoe) */ + q = z*( q1 +z* q2 ); +#endif /* defined(vax)||defined(tahoe) */ + xp= x*p ; + xh= x*half ; + w = xh-(q-xp) ; + p = p+p; + c += x*((xh*w-(q-(p+xp)))/(one-w)+c); + return(z*half+c); + } + /* end of |x| > small */ + + else { + if(x!=zero) (void volatile)(one+small); /* raise the inexact flag */ + return(copysign(zero,x)); + } +} diff --git a/src/kernel/libroot/posix/math/expm1.c b/src/kernel/libroot/posix/math/expm1.c new file mode 100644 index 0000000000..029e7d285b --- /dev/null +++ b/src/kernel/libroot/posix/math/expm1.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* EXPM1(X) + * RETURN THE EXPONENTIAL OF X MINUS ONE + * DOUBLE PRECISION (IEEE 53 BITS, VAX D FORMAT 56 BITS) + * CODED IN C BY K.C. NG, 1/19/85; + * REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/21/85, 4/16/85. + * + * Required system supported functions: + * scalb(x,n) + * copysign(x,y) + * finite(x) + * + * Kernel function: + * exp__E(x,c) + * + * Method: + * 1. Argument Reduction: given the input x, find r and integer k such + * that + * x = k*ln2 + r, |r| <= 0.5*ln2 . + * r will be represented as r := z+c for better accuracy. + * + * 2. Compute EXPM1(r)=exp(r)-1 by + * + * EXPM1(r=z+c) := z + exp__E(z,c) + * + * 3. EXPM1(x) = 2^k * ( EXPM1(r) + 1-2^-k ). + * + * Remarks: + * 1. When k=1 and z < -0.25, we use the following formula for + * better accuracy: + * EXPM1(x) = 2 * ( (z+0.5) + exp__E(z,c) ) + * 2. To avoid rounding error in 1-2^-k where k is large, we use + * EXPM1(x) = 2^k * { [z+(exp__E(z,c)-2^-k )] + 1 } + * when k>56. + * + * Special cases: + * EXPM1(INF) is INF, EXPM1(NaN) is NaN; + * EXPM1(-INF)= -1; + * for finite argument, only EXPM1(0)=0 is exact. + * + * Accuracy: + * EXPM1(x) returns the exact (exp(x)-1) nearly rounded. In a test run with + * 1,166,000 random arguments on a VAX, the maximum observed error was + * .872 ulps (units of the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000) +vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC) +vc(lnhuge, 9.4961163736712506989E1 ,ec1d,43bd,9010,a73e, 7, .BDEC1DA73E9010) +vc(invln2, 1.4426950408889634148E0 ,aa3b,40b8,17f1,295c, 1, .B8AA3B295C17F1) + +ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000) +ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76) +ic(lnhuge, 7.1602103751842355450E2, 9, 1.6602B15B7ECF2) +ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE) + +#ifdef vccast +#define ln2hi vccast(ln2hi) +#define ln2lo vccast(ln2lo) +#define lnhuge vccast(lnhuge) +#define invln2 vccast(invln2) +#endif + +double +expm1(double x) +{ + static double const one=1.0; + static double const half=1.0/2.0; + double z; + double hi; + double lo; + double c; + int k; +#if defined(vax)||defined(tahoe) + static int prec=56; +#else /* defined(vax)||defined(tahoe) */ + static int prec=53; +#endif /* defined(vax)||defined(tahoe) */ + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + + if( x <= lnhuge ) { + if( x >= -40.0 ) { + + /* argument reduction : x - k*ln2 */ + k= invln2 *x+copysign(0.5,x); /* k=NINT(x/ln2) */ + hi=x-k*ln2hi ; + z=hi-(lo=k*ln2lo); + c=(hi-z)-lo; + + if(k==0) return(z+__exp__E(z,c)); + if(k==1) + if(z< -0.25) + {x=z+half;x +=__exp__E(z,c); return(x+x);} + else + {z+=__exp__E(z,c); x=half+z; return(x+x);} + /* end of k=1 */ + + else { + if(k<=prec) + { x=one-scalb(one,-k); z += __exp__E(z,c);} + else if(k<100) + { x = __exp__E(z,c)-scalb(one,-k); x+=z; z=one;} + else + { x = __exp__E(z,c)+z; z=one;} + + return (scalb(x+z,k)); + } + } + /* end of x > lnunfl */ + + else + /* expm1(-big#) rounded to -1 (inexact) */ + if(finite(x)) + { (void volatile)(ln2hi+ln2lo); return(-one);} + + /* expm1(-INF) is -1 */ + else return(-one); + } + /* end of x < lnhuge */ + + else + /* expm1(INF) is INF, expm1(+big#) overflows to INF */ + return( finite(x) ? scalb(one,5000) : x); +} diff --git a/src/kernel/libroot/posix/math/floor.c b/src/kernel/libroot/posix/math/floor.c new file mode 100644 index 0000000000..640ab9fae2 --- /dev/null +++ b/src/kernel/libroot/posix/math/floor.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mathimpl.h" + +vc(L, 4503599627370496.0E0 ,0000,5c00,0000,0000, 55, 1.0) /* 2**55 */ + +ic(L, 4503599627370496.0E0, 52, 1.0) /* 2**52 */ + +#ifdef vccast +#define L vccast(L) +#endif + +/* + * floor(x) := the largest integer no larger than x; + * ceil(x) := -floor(-x), for all real x. + * + * Note: Inexact will be signaled if x is not an integer, as is + * customary for IEEE 754. No other signal can be emitted. + */ +double +floor(x) +double x; +{ + volatile double y; + + if ( +#if !defined(vax)&&!defined(tahoe) + x != x || /* NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + x >= L) /* already an even integer */ + return x; + else if (x < (double)0) + return -ceil(-x); + else { /* now 0 <= x < L */ + y = L+x; /* destructive store must be forced */ + y -= L; /* an integer, and |x-y| < 1 */ + return x < y ? y-(double)1 : y; + } +} + +double +ceil(x) +double x; +{ + volatile double y; + + if ( +#if !defined(vax)&&!defined(tahoe) + x != x || /* NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + x >= L) /* already an even integer */ + return x; + else if (x < (double)0) + return -floor(-x); + else { /* now 0 <= x < L */ + y = L+x; /* destructive store must be forced */ + y -= L; /* an integer, and |x-y| < 1 */ + return x > y ? y+(double)1 : y; + } +} + +#ifndef ns32000 /* rint() is in ./NATIONAL/support.s */ +/* + * algorithm for rint(x) in pseudo-pascal form ... + * + * real rint(x): real x; + * ... delivers integer nearest x in direction of prevailing rounding + * ... mode + * const L = (last consecutive integer)/2 + * = 2**55; for VAX D + * = 2**52; for IEEE 754 Double + * real s,t; + * begin + * if x != x then return x; ... NaN + * if |x| >= L then return x; ... already an integer + * s := copysign(L,x); + * t := x + s; ... = (x+s) rounded to integer + * return t - s + * end; + * + * Note: Inexact will be signaled if x is not an integer, as is + * customary for IEEE 754. No other signal can be emitted. + */ +double +rint(x) +double x; +{ + double s; + volatile double t; + const double one = 1.0; + +#if !defined(vax)&&!defined(tahoe) + if (x != x) /* NaN */ + return (x); +#endif /* !defined(vax)&&!defined(tahoe) */ + if (copysign(x,one) >= L) /* already an integer */ + return (x); + s = copysign(L,x); + t = x + s; /* x+s rounded to integer */ + return (t - s); +} +#endif /* not national */ diff --git a/src/kernel/libroot/posix/math/fmod.c b/src/kernel/libroot/posix/math/fmod.c new file mode 100644 index 0000000000..e4a6425f50 --- /dev/null +++ b/src/kernel/libroot/posix/math/fmod.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* fmod.c + * + * SYNOPSIS + * + * #include + * double fmod(double x, double y) + * + * DESCRIPTION + * + * The fmod function computes the floating-point remainder of x/y. + * + * RETURNS + * + * The fmod function returns the value x-i*y, for some integer i + * such that, if y is nonzero, the result has the same sign as x and + * magnitude less than the magnitude of y. + * + * On a VAX or CCI, + * + * fmod(x,0) traps/faults on floating-point divided-by-zero. + * + * On IEEE-754 conforming machines with "isnan()" primitive, + * + * fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned. + * + */ +#if !defined(vax) && !defined(tahoe) +extern int isnan(),finite(); +#endif /* !defined(vax) && !defined(tahoe) */ +extern double frexp(),ldexp(),fabs(); + +#ifdef TEST_FMOD +static double +_fmod(x,y) +#else /* TEST_FMOD */ +double +fmod(x,y) +#endif /* TEST_FMOD */ +double x,y; +{ + int ir,iy; + double r,w; + + if (y == (double)0 +#if !defined(vax) && !defined(tahoe) /* per "fmod" manual entry, SunOS 4.0 */ + || isnan(y) || !finite(x) +#endif /* !defined(vax) && !defined(tahoe) */ + ) + return (x*y)/(x*y); + + r = fabs(x); + y = fabs(y); + (void)frexp(y,&iy); + while (r >= y) { + (void)frexp(r,&ir); + w = ldexp(y,ir-iy); + r -= w <= r ? w : w*(double)0.5; + } + return x >= (double)0 ? r : -r; +} + +#ifdef TEST_FMOD +extern long random(); +extern double fmod(); + +#define NTEST 10000 +#define NCASES 3 + +static int nfail = 0; + +static void +doit(x,y) +double x,y; +{ + double ro = fmod(x,y),rn = _fmod(x,y); + if (ro != rn) { + (void)printf(" x = 0x%08.8x %08.8x (%24.16e)\n",x,x); + (void)printf(" y = 0x%08.8x %08.8x (%24.16e)\n",y,y); + (void)printf(" fmod = 0x%08.8x %08.8x (%24.16e)\n",ro,ro); + (void)printf("_fmod = 0x%08.8x %08.8x (%24.16e)\n",rn,rn); + (void)printf("\n"); + } +} + +main() +{ + register int i,cases; + double x,y; + + srandom(12345); + for (i = 0; i < NTEST; i++) { + x = (double)random(); + y = (double)random(); + for (cases = 0; cases < NCASES; cases++) { + switch (cases) { + case 0: + break; + case 1: + y = (double)1/y; break; + case 2: + x = (double)1/x; break; + default: + abort(); break; + } + doit(x,y); + doit(x,-y); + doit(-x,y); + doit(-x,-y); + } + } + if (nfail) + (void)printf("Number of failures: %d (out of a total of %d)\n", + nfail,NTEST*NCASES*4); + else + (void)printf("No discrepancies were found\n"); + exit(0); +} +#endif /* TEST_FMOD */ diff --git a/src/kernel/libroot/posix/math/gamma.c b/src/kernel/libroot/posix/math/gamma.c new file mode 100644 index 0000000000..f02c092f56 --- /dev/null +++ b/src/kernel/libroot/posix/math/gamma.c @@ -0,0 +1,347 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This code by P. McIlroy, Oct 1992; + * + * The financial support of UUNET Communications Services is greatfully + * acknowledged. + */ + +#include +#include "mathimpl.h" +#include + +/* METHOD: + * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x)) + * At negative integers, return +Inf, and set errno. + * + * x < 6.5: + * Use argument reduction G(x+1) = xG(x) to reach the + * range [1.066124,2.066124]. Use a rational + * approximation centered at the minimum (x0+1) to + * ensure monotonicity. + * + * x >= 6.5: Use the asymptotic approximation (Stirling's formula) + * adjusted for equal-ripples: + * + * log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x)) + * + * Keep extra precision in multiplying (x-.5)(log(x)-1), to + * avoid premature round-off. + * + * Special values: + * non-positive integer: Set overflow trap; return +Inf; + * x > 171.63: Set overflow trap; return +Inf; + * NaN: Set invalid trap; return NaN + * + * Accuracy: Gamma(x) is accurate to within + * x > 0: error provably < 0.9ulp. + * Maximum observed in 1,000,000 trials was .87ulp. + * x < 0: + * Maximum observed error < 4ulp in 1,000,000 trials. + */ + +static double neg_gam(double); +static double small_gam(double); +static double smaller_gam(double); +static struct Double large_gam(double); +static struct Double ratfun_gam(double, double); + +/* + * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval + * [1.066.., 2.066..] accurate to 4.25e-19. + */ +#define LEFT -.3955078125 /* left boundary for rat. approx */ +#define x0 .461632144968362356785 /* xmin - 1 */ + +#define a0_hi 0.88560319441088874992 +#define a0_lo -.00000000000000004996427036469019695 +#define P0 6.21389571821820863029017800727e-01 +#define P1 2.65757198651533466104979197553e-01 +#define P2 5.53859446429917461063308081748e-03 +#define P3 1.38456698304096573887145282811e-03 +#define P4 2.40659950032711365819348969808e-03 +#define Q0 1.45019531250000000000000000000e+00 +#define Q1 1.06258521948016171343454061571e+00 +#define Q2 -2.07474561943859936441469926649e-01 +#define Q3 -1.46734131782005422506287573015e-01 +#define Q4 3.07878176156175520361557573779e-02 +#define Q5 5.12449347980666221336054633184e-03 +#define Q6 -1.76012741431666995019222898833e-03 +#define Q7 9.35021023573788935372153030556e-05 +#define Q8 6.13275507472443958924745652239e-06 +/* + * Constants for large x approximation (x in [6, Inf]) + * (Accurate to 2.8*10^-19 absolute) + */ +#define lns2pi_hi 0.418945312500000 +#define lns2pi_lo -.000006779295327258219670263595 +#define Pa0 8.33333333333333148296162562474e-02 +#define Pa1 -2.77777777774548123579378966497e-03 +#define Pa2 7.93650778754435631476282786423e-04 +#define Pa3 -5.95235082566672847950717262222e-04 +#define Pa4 8.41428560346653702135821806252e-04 +#define Pa5 -1.89773526463879200348872089421e-03 +#define Pa6 5.69394463439411649408050664078e-03 +#define Pa7 -1.44705562421428915453880392761e-02 + +static const double zero = 0., one = 1.0, tiny = 1e-300; +static int endian; +/* + * TRUNC sets trailing bits in a floating-point number to zero. + * is a temporary variable. + */ +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +#define TRUNC(x) x = (double) (float) (x) +#else +#define _IEEE 1 +#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000 +#define infnan(x) 0.0 +#endif + +double +gamma(x) + double x; +{ + struct Double u; + endian = (*(int *) &one) ? 1 : 0; + + if (x >= 6) { + if(x > 171.63) + return(one/zero); + u = large_gam(x); + return(__exp__D(u.a, u.b)); + } else if (x >= 1.0 + LEFT + x0) { + return (small_gam(x)); + } else if (x > 1.e-17) { + return (smaller_gam(x)); + } else if (x > -1.e-17) { + if (x == 0.0) { + if (!_IEEE) return (infnan(ERANGE)); + else return (one/x); + } + (void volatile)(one+1e-20); /* Raise inexact flag. */ + return (one/x); + } else if (!finite(x)) { + if (_IEEE) /* x = NaN, -Inf */ + return (x*x); + else + return (infnan(EDOM)); + } else { + return (neg_gam(x)); + } +} +/* + * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error. + */ +static +struct Double +large_gam(double x) +{ + double z; + double p; + struct Double t; + struct Double u; + struct Double v; + + z = one/(x*x); + p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7)))))); + p = p/x; + + u = __log__D(x); + u.a -= one; + v.a = (x -= .5); + TRUNC(v.a); + v.b = x - v.a; + t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */ + t.b = v.b*u.a + x*u.b; + /* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */ + t.b += lns2pi_lo; t.b += p; + u.a = lns2pi_hi + t.b; u.a += t.a; + u.b = t.a - u.a; + u.b += lns2pi_hi; u.b += t.b; + return (u); +} +/* + * Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.) + * It also has correct monotonicity. + */ +static +double +small_gam(double x) +{ + double y; + double ym1; + double t; + struct Double yy; + struct Double r; + + y = x - one; + ym1 = y - one; + if (y <= 1.0 + (LEFT + x0)) { + yy = ratfun_gam(y - x0, 0); + return (yy.a + yy.b); + } + r.a = y; + TRUNC(r.a); + yy.a = r.a - one; + y = ym1; + yy.b = r.b = y - yy.a; + /* Argument reduction: G(x+1) = x*G(x) */ + for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) { + t = r.a*yy.a; + r.b = r.a*yy.b + y*r.b; + r.a = t; + TRUNC(r.a); + r.b += (t - r.a); + } + /* Return r*gamma(y). */ + yy = ratfun_gam(y - x0, 0); + y = r.b*(yy.a + yy.b) + r.a*yy.b; + y += yy.a*r.a; + return (y); +} +/* + * Good on (0, 1+x0+LEFT]. Accurate to 1ulp. + */ +static +double +smaller_gam(double x) +{ + double t; + double d; + struct Double r; + struct Double xx; + + if (x < x0 + LEFT) { + t = x, TRUNC(t); + d = (t+x)*(x-t); + t *= t; + xx.a = (t + x), TRUNC(xx.a); + xx.b = x - xx.a; xx.b += t; xx.b += d; + t = (one-x0); t += x; + d = (one-x0); d -= t; d += x; + x = xx.a + xx.b; + } else { + xx.a = x, TRUNC(xx.a); + xx.b = x - xx.a; + t = x - x0; + d = (-x0 -t); d += x; + } + r = ratfun_gam(t, d); + d = r.a/x, TRUNC(d); + r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b; + return (d + r.a/x); +} +/* + * returns (z+c)^2 * P(z)/Q(z) + a0 + */ +static +struct Double +ratfun_gam(double z, double c) +{ + double p; + double q; + struct Double r; + struct Double t; + + q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8))))))); + p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4))); + + /* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */ + p = p/q; + t.a = z, TRUNC(t.a); /* t ~= z + c */ + t.b = (z - t.a) + c; + t.b *= (t.a + z); + q = (t.a *= t.a); /* t = (z+c)^2 */ + TRUNC(t.a); + t.b += (q - t.a); + r.a = p, TRUNC(r.a); /* r = P/Q */ + r.b = p - r.a; + t.b = t.b*p + t.a*r.b + a0_lo; + t.a *= r.a; /* t = (z+c)^2*(P/Q) */ + r.a = t.a + a0_hi, TRUNC(r.a); + r.b = ((a0_hi-r.a) + t.a) + t.b; + return (r); /* r = a0 + t */ +} + +static +double +neg_gam(double x) +{ + int sgn = 1; + struct Double lg; + struct Double lsine; + double y; + double z; + + y = floor(x + .5); + if (y == x) { /* Negative integer. */ + if(!_IEEE) + return (infnan(ERANGE)); + else + return (one/zero); + } + z = fabs(x - y); + y = .5*ceil(x); + if (y == ceil(y)) + sgn = -1; + if (z < .25) + z = sin(M_PI*z); + else + z = cos(M_PI*(0.5-z)); + /* Special case: G(1-x) = Inf; G(x) may be nonzero. */ + if (x < -170) { + if (x < -190) + return ((double)sgn*tiny*tiny); + y = one - x; /* exact: 128 < |x| < 255 */ + lg = large_gam(y); + lsine = __log__D(M_PI/z); /* = TRUNC(log(u)) + small */ + lg.a -= lsine.a; /* exact (opposite signs) */ + lg.b -= lsine.b; + y = -(lg.a + lg.b); + z = (y + lg.a) + lg.b; + y = __exp__D(y, z); + if (sgn < 0) y = -y; + return (y); + } + y = one-x; + if (one-y == x) + y = gamma(y); + else /* 1-x is inexact */ + y = -x*gamma(-x); + if (sgn < 0) y = -y; + return (M_PI / (y*z)); +} diff --git a/src/kernel/libroot/posix/math/ieee.c b/src/kernel/libroot/posix/math/ieee.c new file mode 100644 index 0000000000..ee9fa14e22 --- /dev/null +++ b/src/kernel/libroot/posix/math/ieee.c @@ -0,0 +1,534 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Some IEEE standard 754 recommended functions and remainder and sqrt for + * supporting the C elementary functions. + ****************************************************************************** + * WARNING: + * These codes are developed (in double) to support the C elementary + * functions temporarily. They are not universal, and some of them are very + * slow (in particular, drem and sqrt is extremely inefficient). Each + * computer system should have its implementation of these functions using + * its own assembler. + ****************************************************************************** + * + * IEEE 754 required operations: + * drem(x,p) + * returns x REM y = x - [x/y]*y , where [x/y] is the integer + * nearest x/y; in half way case, choose the even one. + * sqrt(x) + * returns the square root of x correctly rounded according to + * the rounding mod. + * + * IEEE 754 recommended functions: + * (a) copysign(x,y) + * returns x with the sign of y. + * (b) scalb(x,N) + * returns x * (2**N), for integer values N. + * (c) logb(x) + * returns the unbiased exponent of x, a signed integer in + * double precision, except that logb(0) is -INF, logb(INF) + * is +INF, and logb(NAN) is that NAN. + * (d) finite(x) + * returns the value TRUE if -INF < x < +INF and returns + * FALSE otherwise. + * + * + * CODED IN C BY K.C. NG, 11/25/84; + * REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85. + */ + +#include "mathimpl.h" + +#if defined(vax)||defined(tahoe) /* VAX D format */ +#include + static const unsigned short msign=0x7fff , mexp =0x7f80 ; + static const short prep1=57, gap=7, bias=129 ; + static const double novf=1.7E38, nunf=3.0E-39, zero=0.0 ; +#else /* defined(vax)||defined(tahoe) */ + static const unsigned short msign=0x7fff, mexp =0x7ff0 ; + static const short prep1=54, gap=4, bias=1023 ; + static const double novf=1.7E308, nunf=3.0E-308,zero=0.0; +#endif /* defined(vax)||defined(tahoe) */ + +double +scalb(double x, double N) +{ + int k; + +#ifdef national + unsigned short *px=(unsigned short *) &x + 3; +#else /* national */ + unsigned short *px=(unsigned short *) &x; +#endif /* national */ + + if( x == zero ) return(x); + +#if defined(vax)||defined(tahoe) + if( (k= *px & mexp ) != ~msign ) { + if (N < -260) + return(nunf*nunf); + else if (N > 260) { + return(copysign(infnan(ERANGE),x)); + } +#else /* defined(vax)||defined(tahoe) */ + if( (k= *px & mexp ) != mexp ) { + if( N<-2100) return(nunf*nunf); else if(N>2100) return(novf+novf); + if( k == 0 ) { + x *= scalb(1.0,(int)prep1); + N -= prep1; + return(scalb(x,N)); + } +#endif /* defined(vax)||defined(tahoe) */ + + if((k = (k>>gap)+ N) > 0 ) { + if( k < (mexp>>gap) ) *px = (*px&~mexp) | (k< -prep1 ) { + /* gradual underflow */ + *px=(*px&~mexp)|(short)(1<>gap)-bias); +#else /* defined(vax)||defined(tahoe) */ + if( (k= *px & mexp ) != mexp ) + if ( k != 0 ) + return ( (k>>gap) - bias ); + else if( x != zero) + return ( -1022.0 ); + else + return(-(1.0/zero)); + else if(x != x) + return(x); + else + {*px &= msign; return(x);} +#endif /* defined(vax)||defined(tahoe) */ +} + +int +finite(double x) +{ +#if defined(vax)||defined(tahoe) + return(1); +#else /* defined(vax)||defined(tahoe) */ +#ifdef national + return( (*((short *) &x+3 ) & mexp ) != mexp ); +#else /* national */ + return( (*((short *) &x ) & mexp ) != mexp ); +#endif /* national */ +#endif /* defined(vax)||defined(tahoe) */ +} + +double +drem(double x, double p) +{ + short sign; + double hp; + double dp; + double tmp; + unsigned short k; +#ifdef national + unsigned short *px=(unsigned short *) &x +3; + unsigned short *pp=(unsigned short *) &p +3; + unsigned short *pd=(unsigned short *) &dp +3; + unsigned short *pt=(unsigned short *) &tmp+3; +#else /* national */ + unsigned short *px=(unsigned short *) &x; + unsigned short *pp=(unsigned short *) &p; + unsigned short *pd=(unsigned short *) &dp; + unsigned short *pt=(unsigned short *) &tmp; +#endif /* national */ + + *pp &= msign ; + +#if defined(vax)||defined(tahoe) + if( ( *px & mexp ) == ~msign ) /* is x a reserved operand? */ +#else /* defined(vax)||defined(tahoe) */ + if( ( *px & mexp ) == mexp ) +#endif /* defined(vax)||defined(tahoe) */ + return (x-p)-(x-p); /* create nan if x is inf */ + if (p == zero) { +#if defined(vax)||defined(tahoe) + return(infnan(EDOM)); +#else /* defined(vax)||defined(tahoe) */ + return zero/zero; +#endif /* defined(vax)||defined(tahoe) */ + } + +#if defined(vax)||defined(tahoe) + if( ( *pp & mexp ) == ~msign ) /* is p a reserved operand? */ +#else /* defined(vax)||defined(tahoe) */ + if( ( *pp & mexp ) == mexp ) +#endif /* defined(vax)||defined(tahoe) */ + { if (p != p) return p; else return x;} + + else if ( ((*pp & mexp)>>gap) <= 1 ) + /* subnormal p, or almost subnormal p */ + { double b; b=scalb(1.0,(int)prep1); + p *= b; x = drem(x,p); x *= b; return(drem(x,p)/b);} + else if ( p >= novf/2) + { p /= 2 ; x /= 2; return(drem(x,p)*2);} + else + { + dp=p+p; hp=p/2; + sign= *px & ~msign ; + *px &= msign ; + while ( x > dp ) + { + k=(*px & mexp) - (*pd & mexp) ; + tmp = dp ; + *pt += k ; + +#if defined(vax)||defined(tahoe) + if( x < tmp ) *pt -= 128 ; +#else /* defined(vax)||defined(tahoe) */ + if( x < tmp ) *pt -= 16 ; +#endif /* defined(vax)||defined(tahoe) */ + + x -= tmp ; + } + if ( x > hp ) + { x -= p ; if ( x >= hp ) x -= p ; } + +#if defined(vax)||defined(tahoe) + if (x) +#endif /* defined(vax)||defined(tahoe) */ + *px ^= sign; + return( x); + + } +} + + +double +sqrt(double x) +{ + double q; + double s; + double b; + double r; + double t; + double const zero=0.0; + int m; + int n; + int i; +#if defined(vax)||defined(tahoe) + int k=54; +#else /* defined(vax)||defined(tahoe) */ + int k=51; +#endif /* defined(vax)||defined(tahoe) */ + + /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */ + if(x!=x||x==zero) return(x); + + /* sqrt(negative) is invalid */ + if(x1.0) t=1; /* b>1 : Round-to-(+INF) */ + if(t>=0) q+=r; } /* else: Round-to-nearest */ + else { + s *= 2; x *= 4; + t = (x-s)-1; + b=1.0+3*r/4; if(b==1.0) goto end; + b=1.0+r/4; if(b>1.0) t=1; + if(t>=0) q+=r; } + +end: return(scalb(q,n)); +} + +#if 0 +/* DREM(X,Y) + * RETURN X REM Y =X-N*Y, N=[X/Y] ROUNDED (ROUNDED TO EVEN IN THE HALF WAY CASE) + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * INTENDED FOR ASSEMBLY LANGUAGE + * CODED IN C BY K.C. NG, 3/23/85, 4/8/85. + * + * Warning: this code should not get compiled in unless ALL of + * the following machine-dependent routines are supplied. + * + * Required machine dependent functions (not on a VAX): + * swapINX(i): save inexact flag and reset it to "i" + * swapENI(e): save inexact enable and reset it to "e" + */ + +double drem(x,y) +double x,y; +{ + +#ifdef national /* order of words in floating point number */ + static const n0=3,n1=2,n2=1,n3=0; +#else /* VAX, SUN, ZILOG, TAHOE */ + static const n0=0,n1=1,n2=2,n3=3; +#endif + + static const unsigned short mexp =0x7ff0, m25 =0x0190, m57 =0x0390; + static const double zero=0.0; + double hy,y1,t,t1; + short k; + long n; + int i,e; + unsigned short xexp,yexp, *px =(unsigned short *) &x , + nx,nf, *py =(unsigned short *) &y , + sign, *pt =(unsigned short *) &t , + *pt1 =(unsigned short *) &t1 ; + + xexp = px[n0] & mexp ; /* exponent of x */ + yexp = py[n0] & mexp ; /* exponent of y */ + sign = px[n0] &0x8000; /* sign of x */ + +/* return NaN if x is NaN, or y is NaN, or x is INF, or y is zero */ + if(x!=x) return(x); if(y!=y) return(y); /* x or y is NaN */ + if( xexp == mexp ) return(zero/zero); /* x is INF */ + if(y==zero) return(y/y); + +/* save the inexact flag and inexact enable in i and e respectively + * and reset them to zero + */ + i=swapINX(0); e=swapENI(0); + +/* subnormal number */ + nx=0; + if(yexp==0) {t=1.0,pt[n0]+=m57; y*=t; nx=m57;} + +/* if y is tiny (biased exponent <= 57), scale up y to y*2**57 */ + if( yexp <= m57 ) {py[n0]+=m57; nx+=m57; yexp+=m57;} + + nf=nx; + py[n0] &= 0x7fff; + px[n0] &= 0x7fff; + +/* mask off the least significant 27 bits of y */ + t=y; pt[n3]=0; pt[n2]&=0xf800; y1=t; + +/* LOOP: argument reduction on x whenever x > y */ +loop: + while ( x > y ) + { + t=y; + t1=y1; + xexp=px[n0]&mexp; /* exponent of x */ + k=xexp-yexp-m25; + if(k>0) /* if x/y >= 2**26, scale up y so that x/y < 2**26 */ + {pt[n0]+=k;pt1[n0]+=k;} + n=x/t; x=(x-n*t1)-n*(t-t1); + } + /* end while (x > y) */ + + if(nx!=0) {t=1.0; pt[n0]+=nx; x*=t; nx=0; goto loop;} + +/* final adjustment */ + + hy=y/2.0; + if(x>hy||((x==hy)&&n%2==1)) x-=y; + px[n0] ^= sign; + if(nf!=0) { t=1.0; pt[n0]-=nf; x*=t;} + +/* restore inexact flag and inexact enable */ + swapINX(i); swapENI(e); + + return(x); +} +#endif + +#if 0 +/* SQRT + * RETURN CORRECTLY ROUNDED (ACCORDING TO THE ROUNDING MODE) SQRT + * FOR IEEE DOUBLE PRECISION ONLY, INTENDED FOR ASSEMBLY LANGUAGE + * CODED IN C BY K.C. NG, 3/22/85. + * + * Warning: this code should not get compiled in unless ALL of + * the following machine-dependent routines are supplied. + * + * Required machine dependent functions: + * swapINX(i) ...return the status of INEXACT flag and reset it to "i" + * swapRM(r) ...return the current Rounding Mode and reset it to "r" + * swapENI(e) ...return the status of inexact enable and reset it to "e" + * addc(t) ...perform t=t+1 regarding t as a 64 bit unsigned integer + * subc(t) ...perform t=t-1 regarding t as a 64 bit unsigned integer + */ + +static const unsigned long table[] = { +0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740, +58733, 67158, 75992, 85215, 83599, 71378, 60428, 50647, 41945, 34246, 27478, +21581, 16499, 12183, 8588, 5674, 3403, 1742, 661, 130, }; + +double newsqrt(x) +double x; +{ + double y,z,t,addc(),subc() + double const b54=134217728.*134217728.; /* b54=2**54 */ + long mx,scalx; + long const mexp=0x7ff00000; + int i,j,r,e,swapINX(),swapRM(),swapENI(); + unsigned long *py=(unsigned long *) &y , + *pt=(unsigned long *) &t , + *px=(unsigned long *) &x ; +#ifdef national /* ordering of word in a floating point number */ + const int n0=1, n1=0; +#else + const int n0=0, n1=1; +#endif +/* Rounding Mode: RN ...round-to-nearest + * RZ ...round-towards 0 + * RP ...round-towards +INF + * RM ...round-towards -INF + */ + const int RN=0,RZ=1,RP=2,RM=3; + /* machine dependent: work on a Zilog Z8070 + * and a National 32081 & 16081 + */ + +/* exceptions */ + if(x!=x||x==0.0) return(x); /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */ + if(x<0) return((x-x)/(x-x)); /* sqrt(negative) is invalid */ + if((mx=px[n0]&mexp)==mexp) return(x); /* sqrt(+INF) is +INF */ + +/* save, reset, initialize */ + e=swapENI(0); /* ...save and reset the inexact enable */ + i=swapINX(0); /* ...save INEXACT flag */ + r=swapRM(RN); /* ...save and reset the Rounding Mode to RN */ + scalx=0; + +/* subnormal number, scale up x to x*2**54 */ + if(mx==0) {x *= b54 ; scalx-=0x01b00000;} + +/* scale x to avoid intermediate over/underflow: + * if (x > 2**512) x=x/2**512; if (x < 2**-512) x=x*2**512 */ + if(mx>0x5ff00000) {px[n0] -= 0x20000000; scalx+= 0x10000000;} + if(mx<0x1ff00000) {px[n0] += 0x20000000; scalx-= 0x10000000;} + +/* magic initial approximation to almost 8 sig. bits */ + py[n0]=(px[n0]>>1)+0x1ff80000; + py[n0]=py[n0]-table[(py[n0]>>15)&31]; + +/* Heron's rule once with correction to improve y to almost 18 sig. bits */ + t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; + +/* triple to almost 56 sig. bits; now y approx. sqrt(x) to within 1 ulp */ + t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; + t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; + +/* twiddle last bit to force y correctly rounded */ + swapRM(RZ); /* ...set Rounding Mode to round-toward-zero */ + swapINX(0); /* ...clear INEXACT flag */ + swapENI(e); /* ...restore inexact enable status */ + t=x/y; /* ...chopped quotient, possibly inexact */ + j=swapINX(i); /* ...read and restore inexact flag */ + if(j==0) { if(t==y) goto end; else t=subc(t); } /* ...t=t-ulp */ + b54+0.1; /* ..trigger inexact flag, sqrt(x) is inexact */ + if(r==RN) t=addc(t); /* ...t=t+ulp */ + else if(r==RP) { t=addc(t);y=addc(y);}/* ...t=t+ulp;y=y+ulp; */ + y=y+t; /* ...chopped sum */ + py[n0]=py[n0]-0x00100000; /* ...correctly rounded sqrt(x) */ +end: py[n0]=py[n0]+scalx; /* ...scale back y */ + swapRM(r); /* ...restore Rounding Mode */ + return(y); +} +#endif diff --git a/src/kernel/libroot/posix/math/j0.c b/src/kernel/libroot/posix/math/j0.c new file mode 100644 index 0000000000..73040e8085 --- /dev/null +++ b/src/kernel/libroot/posix/math/j0.c @@ -0,0 +1,461 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * 16 December 1992 + * Minor modifications by Peter McIlroy to adapt non-IEEE architecture. + */ + +/* + * ==================================================== + * Copyright (C) 1992 by Sun Microsystems, Inc. + * + * 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. + * ==================================================== + * + * ******************* WARNING ******************** + * This is an alpha version of SunPro's FDLIBM (Freely + * Distributable Math Library) for IEEE double precision + * arithmetic. FDLIBM is a basic math library written + * in C that runs on machines that conform to IEEE + * Standard 754/854. This alpha version is distributed + * for testing purpose. Those who use this software + * should report any bugs to + * + * fdlibm-comments@sunpro.eng.sun.com + * + * -- K.C. Ng, Oct 12, 1992 + * ************************************************ + */ + +/* double j0(double x), y0(double x) + * Bessel function of the first and second kinds of order zero. + * Method -- j0(x): + * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... + * 2. Reduce x to |x| since j0(x)=j0(-x), and + * for x in (0,2) + * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; + * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) + * for x in (2,inf) + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * as follow: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (cos(x) + sin(x)) + * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j0(nan)= nan + * j0(0) = 1 + * j0(inf) = 0 + * + * Method -- y0(x): + * 1. For x<2. + * Since + * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) + * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. + * We use the following function to approximate y0, + * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 + * where + * U(z) = u0 + u1*z + ... + u6*z^6 + * V(z) = 1 + v1*z + ... + v4*z^4 + * with absolute approximation error bounded by 2**-72. + * Note: For tiny x, U/V = u0 and j0(x)~1, hence + * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) + * 2. For x>=2. + * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * by the method mentioned above. + * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. + */ + +#include +#include +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +#else +#define _IEEE 1 +#define infnan(x) (0.0) +#endif + +static double pzero(double); +static double qzero(double); + +static double const huge = 1e300; +static double const zero = 0.0; +static double const one = 1.0; +static double const invsqrtpi= 5.641895835477562869480794515607725858441e-0001; +static double const tpi = 0.636619772367581343075535053490057448; + /* R0/S0 on [0, 2.00] */ +static double const r02 = 1.562499999999999408594634421055018003102e-0002; +static double const r03 = -1.899792942388547334476601771991800712355e-0004; +static double const r04 = 1.829540495327006565964161150603950916854e-0006; +static double const r05 = -4.618326885321032060803075217804816988758e-0009; +static double const s01 = 1.561910294648900170180789369288114642057e-0002; +static double const s02 = 1.169267846633374484918570613449245536323e-0004; +static double const s03 = 5.135465502073181376284426245689510134134e-0007; +static double const s04 = 1.166140033337900097836930825478674320464e-0009; + +double +j0(double x) +{ + double z; + double s; + double c; + double ss; + double cc; + double r; + double u; + double v; + + if (!finite(x)) { + if (_IEEE) return one/(x*x); + else return (0); + } + x = fabs(x); + if (x >= 2.0) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = s-c; + cc = s+c; + if (x < .5 * DBL_MAX) { /* make sure x+x not overflow */ + z = -cos(x+x); + if ((s*c) 6.80564733841876927e+38) /* 2^129 */ + z = (invsqrtpi*cc)/sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*cc-v*ss)/sqrt(x); + } + return z; + } + if (x < 1.220703125e-004) { /* |x| < 2**-13 */ + if (huge+x > one) { /* raise inexact if x != 0 */ + if (x < 7.450580596923828125e-009) /* |x|<2**-27 */ + return one; + else return (one - 0.25*x*x); + } + } + z = x*x; + r = z*(r02+z*(r03+z*(r04+z*r05))); + s = one+z*(s01+z*(s02+z*(s03+z*s04))); + if (x < one) { /* |x| < 1.00 */ + return (one + z*(-0.25+(r/s))); + } else { + u = 0.5*x; + return ((one+u)*(one-u)+z*(r/s)); + } +} + +static double const u00 = -7.380429510868722527422411862872999615628e-0002; +static double const u01 = 1.766664525091811069896442906220827182707e-0001; +static double const u02 = -1.381856719455968955440002438182885835344e-0002; +static double const u03 = 3.474534320936836562092566861515617053954e-0004; +static double const u04 = -3.814070537243641752631729276103284491172e-0006; +static double const u05 = 1.955901370350229170025509706510038090009e-0008; +static double const u06 = -3.982051941321034108350630097330144576337e-0011; +static double const v01 = 1.273048348341237002944554656529224780561e-0002; +static double const v02 = 7.600686273503532807462101309675806839635e-0005; +static double const v03 = 2.591508518404578033173189144579208685163e-0007; +static double const v04 = 4.411103113326754838596529339004302243157e-0010; + +double +y0(double x) +{ + double z; + double s; + double c; + double ss; + double cc; + double u; + double v; + /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ + if (!finite(x)) { + if (_IEEE) + return (one/(x+x*x)); + else + return (0); + } + if (x == 0) { + if (_IEEE) return (-one/zero); + else return(infnan(-ERANGE)); + } + if (x<0) { + if (_IEEE) return (zero/zero); + else return (infnan(EDOM)); + } + if (x >= 2.00) { /* |x| >= 2.0 */ + /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) + * where x0 = x-pi/4 + * Better formula: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) + cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + s = sin(x); + c = cos(x); + ss = s-c; + cc = s+c; + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if (x < .5 * DBL_MAX) { /* make sure x+x not overflow */ + z = -cos(x+x); + if ((s*c) 6.80564733841876927e+38) /* > 2^129 */ + z = (invsqrtpi*ss)/sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*ss+v*cc)/sqrt(x); + } + return z; + } + if (x <= 7.450580596923828125e-009) { /* x < 2**-27 */ + return (u00 + tpi*log(x)); + } + z = x*x; + u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); + v = one+z*(v01+z*(v02+z*(v03+z*v04))); + return (u/v + tpi*(j0(x)*log(x))); +} + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pzero(x)-1-R/S | <= 2 ** ( -60.26) + */ +static double const pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.0, + -7.031249999999003994151563066182798210142e-0002, + -8.081670412753498508883963849859423939871e+0000, + -2.570631056797048755890526455854482662510e+0002, + -2.485216410094288379417154382189125598962e+0003, + -5.253043804907295692946647153614119665649e+0003, +}; +static double const ps8[5] = { + 1.165343646196681758075176077627332052048e+0002, + 3.833744753641218451213253490882686307027e+0003, + 4.059785726484725470626341023967186966531e+0004, + 1.167529725643759169416844015694440325519e+0005, + 4.762772841467309430100106254805711722972e+0004, +}; + +static double const pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -1.141254646918944974922813501362824060117e-0011, + -7.031249408735992804117367183001996028304e-0002, + -4.159610644705877925119684455252125760478e+0000, + -6.767476522651671942610538094335912346253e+0001, + -3.312312996491729755731871867397057689078e+0002, + -3.464333883656048910814187305901796723256e+0002, +}; +static double const ps5[5] = { + 6.075393826923003305967637195319271932944e+0001, + 1.051252305957045869801410979087427910437e+0003, + 5.978970943338558182743915287887408780344e+0003, + 9.625445143577745335793221135208591603029e+0003, + 2.406058159229391070820491174867406875471e+0003, +}; + +static double const pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + -2.547046017719519317420607587742992297519e-0009, + -7.031196163814817199050629727406231152464e-0002, + -2.409032215495295917537157371488126555072e+0000, + -2.196597747348830936268718293366935843223e+0001, + -5.807917047017375458527187341817239891940e+0001, + -3.144794705948885090518775074177485744176e+0001, +}; +static double const ps3[5] = { + 3.585603380552097167919946472266854507059e+0001, + 3.615139830503038919981567245265266294189e+0002, + 1.193607837921115243628631691509851364715e+0003, + 1.127996798569074250675414186814529958010e+0003, + 1.735809308133357510239737333055228118910e+0002, +}; + +static double const pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + -8.875343330325263874525704514800809730145e-0008, + -7.030309954836247756556445443331044338352e-0002, + -1.450738467809529910662233622603401167409e+0000, + -7.635696138235277739186371273434739292491e+0000, + -1.119316688603567398846655082201614524650e+0001, + -3.233645793513353260006821113608134669030e+0000, +}; +static double const ps2[5] = { + 2.222029975320888079364901247548798910952e+0001, + 1.362067942182152109590340823043813120940e+0002, + 2.704702786580835044524562897256790293238e+0002, + 1.538753942083203315263554770476850028583e+0002, + 1.465761769482561965099880599279699314477e+0001, +}; + +static +double +pzero(double x) +{ + double const *p; + double const *q; + double z; + double r; + double s; + if (x >= 8.00) {p = pr8; q= ps8;} + else if (x >= 4.54545211791992188) {p = pr5; q= ps5;} + else if (x >= 2.85714149475097656) {p = pr3; q= ps3;} + else if (x >= 2.00) {p = pr2; q= ps2;} + else {p = 0; q= 0; } /* should never happen */ + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate pzero by + * qzero(x) = s*(-1.25 + (R/S)) + * where R = qr0 + qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs0*s^2 + ... + qs5*s^12 + * and + * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +static double const qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.0, + 7.324218749999350414479738504551775297096e-0002, + 1.176820646822526933903301695932765232456e+0001, + 5.576733802564018422407734683549251364365e+0002, + 8.859197207564685717547076568608235802317e+0003, + 3.701462677768878501173055581933725704809e+0004, +}; +static double const qs8[6] = { + 1.637760268956898345680262381842235272369e+0002, + 8.098344946564498460163123708054674227492e+0003, + 1.425382914191204905277585267143216379136e+0005, + 8.033092571195144136565231198526081387047e+0005, + 8.405015798190605130722042369969184811488e+0005, + -3.438992935378666373204500729736454421006e+0005, +}; + +static double const qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.840859635945155400568380711372759921179e-0011, + 7.324217666126847411304688081129741939255e-0002, + 5.835635089620569401157245917610984757296e+0000, + 1.351115772864498375785526599119895942361e+0002, + 1.027243765961641042977177679021711341529e+0003, + 1.989977858646053872589042328678602481924e+0003, +}; +static double const qs5[6] = { + 8.277661022365377058749454444343415524509e+0001, + 2.077814164213929827140178285401017305309e+0003, + 1.884728877857180787101956800212453218179e+0004, + 5.675111228949473657576693406600265778689e+0004, + 3.597675384251145011342454247417399490174e+0004, + -5.354342756019447546671440667961399442388e+0003, +}; + +static double const qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + 4.377410140897386263955149197672576223054e-0009, + 7.324111800429115152536250525131924283018e-0002, + 3.344231375161707158666412987337679317358e+0000, + 4.262184407454126175974453269277100206290e+0001, + 1.708080913405656078640701512007621675724e+0002, + 1.667339486966511691019925923456050558293e+0002, +}; +static double const qs3[6] = { + 4.875887297245871932865584382810260676713e+0001, + 7.096892210566060535416958362640184894280e+0002, + 3.704148226201113687434290319905207398682e+0003, + 6.460425167525689088321109036469797462086e+0003, + 2.516333689203689683999196167394889715078e+0003, + -1.492474518361563818275130131510339371048e+0002, +}; + +static double const qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.504444448869832780257436041633206366087e-0007, + 7.322342659630792930894554535717104926902e-0002, + 1.998191740938159956838594407540292600331e+0000, + 1.449560293478857407645853071687125850962e+0001, + 3.166623175047815297062638132537957315395e+0001, + 1.625270757109292688799540258329430963726e+0001, +}; +static double const qs2[6] = { + 3.036558483552191922522729838478169383969e+0001, + 2.693481186080498724211751445725708524507e+0002, + 8.447837575953201460013136756723746023736e+0002, + 8.829358451124885811233995083187666981299e+0002, + 2.126663885117988324180482985363624996652e+0002, + -5.310954938826669402431816125780738924463e+0000, +}; + +static +double +qzero(double x) +{ + double const *p; + double const *q; + double s; + double r; + double z; + if (x >= 8.00) {p = qr8; q= qs8;} + else if (x >= 4.54545211791992188) {p = qr5; q= qs5;} + else if (x >= 2.85714149475097656) {p = qr3; q= qs3;} + else if (x >= 2.00) {p = qr2; q= qs2;} + else {p = 0; q= 0; } /* should never happen */ + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); + return (-.125 + r/s)/x; +} diff --git a/src/kernel/libroot/posix/math/j1.c b/src/kernel/libroot/posix/math/j1.c new file mode 100644 index 0000000000..a633020cc0 --- /dev/null +++ b/src/kernel/libroot/posix/math/j1.c @@ -0,0 +1,469 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * 16 December 1992 + * Minor modifications by Peter McIlroy to adapt non-IEEE architecture. + */ + +/* + * ==================================================== + * Copyright (C) 1992 by Sun Microsystems, Inc. + * + * 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. + * ==================================================== + * + * ******************* WARNING ******************** + * This is an alpha version of SunPro's FDLIBM (Freely + * Distributable Math Library) for IEEE double precision + * arithmetic. FDLIBM is a basic math library written + * in C that runs on machines that conform to IEEE + * Standard 754/854. This alpha version is distributed + * for testing purpose. Those who use this software + * should report any bugs to + * + * fdlibm-comments@sunpro.eng.sun.com + * + * -- K.C. Ng, Oct 12, 1992 + * ************************************************ + */ + +/* double j1(double x), y1(double x) + * Bessel function of the first and second kinds of order zero. + * Method -- j1(x): + * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... + * 2. Reduce x to |x| since j1(x)=-j1(-x), and + * for x in (0,2) + * j1(x) = x/2 + x*z*R0/S0, where z = x*x; + * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) + * for x in (2,inf) + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * as follows: + * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (sin(x) + cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j1(nan)= nan + * j1(0) = 0 + * j1(inf) = 0 + * + * Method -- y1(x): + * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN + * 2. For x<2. + * Since + * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) + * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. + * We use the following function to approximate y1, + * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 + * where for x in [0,2] (abs err less than 2**-65.89) + * U(z) = u0 + u1*z + ... + u4*z^4 + * V(z) = 1 + v1*z + ... + v5*z^5 + * Note: For tiny x, 1/x dominate y1 and hence + * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) + * 3. For x>=2. + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * by method mentioned above. + */ + +#include +#include + +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +#else +#define _IEEE 1 +#define infnan(x) (0.0) +#endif + +static double pone(double); +static double qone(double); + +static double const huge = 1e300; +static double const zero = 0.0; +static double const one = 1.0; +static double const invsqrtpi= 5.641895835477562869480794515607725858441e-0001; +static double const tpi = 0.636619772367581343075535053490057448; + + /* R0/S0 on [0,2] */ +static double const r00 = -6.250000000000000020842322918309200910191e-0002; +static double const r01 = 1.407056669551897148204830386691427791200e-0003; +static double const r02 = -1.599556310840356073980727783817809847071e-0005; +static double const r03 = 4.967279996095844750387702652791615403527e-0008; +static double const s01 = 1.915375995383634614394860200531091839635e-0002; +static double const s02 = 1.859467855886309024045655476348872850396e-0004; +static double const s03 = 1.177184640426236767593432585906758230822e-0006; +static double const s04 = 5.046362570762170559046714468225101016915e-0009; +static double const s05 = 1.235422744261379203512624973117299248281e-0011; + +#define two_129 6.80564733841876926e+038 /* 2^129 */ +#define two_m54 5.55111512312578270e-017 /* 2^-54 */ +double +j1(double x) +{ + double z; + double s; + double c; + double ss; + double cc; + double r; + double u; + double v; + double y; + + y = fabs(x); + if (!finite(x)) { /* Inf or NaN */ + if (_IEEE && x != x) + return(x); + else + return (copysign(x, zero)); + } + y = fabs(x); + if (y >= 2) { /* |x| >= 2.0 */ + s = sin(y); + c = cos(y); + ss = -s-c; + cc = s-c; + if (y < .5*DBL_MAX) { /* make sure y+y not overflow */ + z = cos(y+y); + if ((s*c) two_129) /* x > 2^129 */ + z = (invsqrtpi*cc)/sqrt(y); + else +#endif /* defined(vax) || defined(tahoe) */ + { + u = pone(y); v = qone(y); + z = invsqrtpi*(u*cc-v*ss)/sqrt(y); + } + if (x < 0) return -z; + else return z; + } + if (y < 7.450580596923828125e-009) { /* |x|<2**-27 */ + if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */ + } + z = x*x; + r = z*(r00+z*(r01+z*(r02+z*r03))); + s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); + r *= x; + return (x*0.5+r/s); +} + +static double const u0[5] = { + -1.960570906462389484206891092512047539632e-0001, + 5.044387166398112572026169863174882070274e-0002, + -1.912568958757635383926261729464141209569e-0003, + 2.352526005616105109577368905595045204577e-0005, + -9.190991580398788465315411784276789663849e-0008, +}; +static double const v0[5] = { + 1.991673182366499064031901734535479833387e-0002, + 2.025525810251351806268483867032781294682e-0004, + 1.356088010975162198085369545564475416398e-0006, + 6.227414523646214811803898435084697863445e-0009, + 1.665592462079920695971450872592458916421e-0011, +}; + +double +y1(double x) +{ + double z; + double s; + double c; + double ss; + double cc; + double u; + double v; + + /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ + if (!finite(x)) { + if (!_IEEE) return (infnan(EDOM)); + else if (x < 0) + return(zero/zero); + else if (x > 0) + return (0); + else + return(x); + } + if (x <= 0) { + if (_IEEE && x == 0) return -one/zero; + else if(x == 0) return(infnan(-ERANGE)); + else if(_IEEE) return (zero/zero); + else return(infnan(EDOM)); + } + if (x >= 2) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = -s-c; + cc = s-c; + if (x < .5 * DBL_MAX) /* make sure x+x not overflow */ + { + z = cos(x+x); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) + * where x0 = x-3pi/4 + * Better formula: + * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (cos(x) + sin(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + if (_IEEE && x>two_129) + z = (invsqrtpi*ss)/sqrt(x); + else { + u = pone(x); v = qone(x); + z = invsqrtpi*(u*ss+v*cc)/sqrt(x); + } + return z; + } + if (x <= two_m54) { /* x < 2**-54 */ + return (-tpi/x); + } + z = x*x; + u = u0[0]+z*(u0[1]+z*(u0[2]+z*(u0[3]+z*u0[4]))); + v = one+z*(v0[0]+z*(v0[1]+z*(v0[2]+z*(v0[3]+z*v0[4])))); + return (x*(u/v) + tpi*(j1(x)*log(x)-one/x)); +} + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pone(x)-1-R/S | <= 2 ** ( -60.06) + */ + +static double const pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.0, + 1.171874999999886486643746274751925399540e-0001, + 1.323948065930735690925827997575471527252e+0001, + 4.120518543073785433325860184116512799375e+0002, + 3.874745389139605254931106878336700275601e+0003, + 7.914479540318917214253998253147871806507e+0003, +}; +static double const ps8[5] = { + 1.142073703756784104235066368252692471887e+0002, + 3.650930834208534511135396060708677099382e+0003, + 3.695620602690334708579444954937638371808e+0004, + 9.760279359349508334916300080109196824151e+0004, + 3.080427206278887984185421142572315054499e+0004, +}; + +static double const pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.319905195562435287967533851581013807103e-0011, + 1.171874931906140985709584817065144884218e-0001, + 6.802751278684328781830052995333841452280e+0000, + 1.083081829901891089952869437126160568246e+0002, + 5.176361395331997166796512844100442096318e+0002, + 5.287152013633375676874794230748055786553e+0002, +}; +static double const ps5[5] = { + 5.928059872211313557747989128353699746120e+0001, + 9.914014187336144114070148769222018425781e+0002, + 5.353266952914879348427003712029704477451e+0003, + 7.844690317495512717451367787640014588422e+0003, + 1.504046888103610723953792002716816255382e+0003, +}; + +static double const pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + 3.025039161373736032825049903408701962756e-0009, + 1.171868655672535980750284752227495879921e-0001, + 3.932977500333156527232725812363183251138e+0000, + 3.511940355916369600741054592597098912682e+0001, + 9.105501107507812029367749771053045219094e+0001, + 4.855906851973649494139275085628195457113e+0001, +}; +static double const ps3[5] = { + 3.479130950012515114598605916318694946754e+0001, + 3.367624587478257581844639171605788622549e+0002, + 1.046871399757751279180649307467612538415e+0003, + 8.908113463982564638443204408234739237639e+0002, + 1.037879324396392739952487012284401031859e+0002, +}; + +static double const pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.077108301068737449490056513753865482831e-0007, + 1.171762194626833490512746348050035171545e-0001, + 2.368514966676087902251125130227221462134e+0000, + 1.224261091482612280835153832574115951447e+0001, + 1.769397112716877301904532320376586509782e+0001, + 5.073523125888185399030700509321145995160e+0000, +}; +static double const ps2[5] = { + 2.143648593638214170243114358933327983793e+0001, + 1.252902271684027493309211410842525120355e+0002, + 2.322764690571628159027850677565128301361e+0002, + 1.176793732871470939654351793502076106651e+0002, + 8.364638933716182492500902115164881195742e+0000, +}; + +static +double +pone(double x) +{ + double const *p; + double const *q; + double z; + double r; + double s; + + if (x >= 8.0) {p = pr8; q= ps8;} + else if (x >= 4.54545211791992188) {p = pr5; q= ps5;} + else if (x >= 2.85714149475097656) {p = pr3; q= ps3;} + else /* if (x >= 2.0) */ {p = pr2; q= ps2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); + return (one + r/s); +} + + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs1*s^2 + ... + qs6*s^12 + * and + * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +static double const qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.0, + -1.025390624999927207385863635575804210817e-0001, + -1.627175345445899724355852152103771510209e+0001, + -7.596017225139501519843072766973047217159e+0002, + -1.184980667024295901645301570813228628541e+0004, + -4.843851242857503225866761992518949647041e+0004, +}; +static double const qs8[6] = { + 1.613953697007229231029079421446916397904e+0002, + 7.825385999233484705298782500926834217525e+0003, + 1.338753362872495800748094112937868089032e+0005, + 7.196577236832409151461363171617204036929e+0005, + 6.666012326177764020898162762642290294625e+0005, + -2.944902643038346618211973470809456636830e+0005, +}; + +static double const qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -2.089799311417640889742251585097264715678e-0011, + -1.025390502413754195402736294609692303708e-0001, + -8.056448281239359746193011295417408828404e+0000, + -1.836696074748883785606784430098756513222e+0002, + -1.373193760655081612991329358017247355921e+0003, + -2.612444404532156676659706427295870995743e+0003, +}; +static double const qs5[6] = { + 8.127655013843357670881559763225310973118e+0001, + 1.991798734604859732508048816860471197220e+0003, + 1.746848519249089131627491835267411777366e+0004, + 4.985142709103522808438758919150738000353e+0004, + 2.794807516389181249227113445299675335543e+0004, + -4.719183547951285076111596613593553911065e+0003, +}; + +static double const qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + -5.078312264617665927595954813341838734288e-0009, + -1.025378298208370901410560259001035577681e-0001, + -4.610115811394734131557983832055607679242e+0000, + -5.784722165627836421815348508816936196402e+0001, + -2.282445407376317023842545937526967035712e+0002, + -2.192101284789093123936441805496580237676e+0002, +}; +static double const qs3[6] = { + 4.766515503237295155392317984171640809318e+0001, + 6.738651126766996691330687210949984203167e+0002, + 3.380152866795263466426219644231687474174e+0003, + 5.547729097207227642358288160210745890345e+0003, + 1.903119193388108072238947732674639066045e+0003, + -1.352011914443073322978097159157678748982e+0002, +}; + +static double const qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + -1.783817275109588656126772316921194887979e-0007, + -1.025170426079855506812435356168903694433e-0001, + -2.752205682781874520495702498875020485552e+0000, + -1.966361626437037351076756351268110418862e+0001, + -4.232531333728305108194363846333841480336e+0001, + -2.137192117037040574661406572497288723430e+0001, +}; +static double const qs2[6] = { + 2.953336290605238495019307530224241335502e+0001, + 2.529815499821905343698811319455305266409e+0002, + 7.575028348686454070022561120722815892346e+0002, + 7.393932053204672479746835719678434981599e+0002, + 1.559490033366661142496448853793707126179e+0002, + -4.959498988226281813825263003231704397158e+0000, +}; + +static +double +qone(double x) +{ + double const *p; + double const *q; + double s; + double r; + double z; + if (x >= 8.0) {p = qr8; q= qs8;} + else if (x >= 4.54545211791992188) {p = qr5; q= qs5;} + else if (x >= 2.85714149475097656) {p = qr3; q= qs3;} + else /* if (x >= 2.0) */ {p = qr2; q= qs2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); + return (.375 + r/s)/x; +} diff --git a/src/kernel/libroot/posix/math/jn.c b/src/kernel/libroot/posix/math/jn.c new file mode 100644 index 0000000000..f8e17cb517 --- /dev/null +++ b/src/kernel/libroot/posix/math/jn.c @@ -0,0 +1,318 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * 16 December 1992 + * Minor modifications by Peter McIlroy to adapt non-IEEE architecture. + */ + +/* + * ==================================================== + * Copyright (C) 1992 by Sun Microsystems, Inc. + * + * 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. + * ==================================================== + * + * ******************* WARNING ******************** + * This is an alpha version of SunPro's FDLIBM (Freely + * Distributable Math Library) for IEEE double precision + * arithmetic. FDLIBM is a basic math library written + * in C that runs on machines that conform to IEEE + * Standard 754/854. This alpha version is distributed + * for testing purpose. Those who use this software + * should report any bugs to + * + * fdlibm-comments@sunpro.eng.sun.com + * + * -- K.C. Ng, Oct 12, 1992 + * ************************************************ + */ + +/* + * jn(int n, double x), yn(int n, double x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for nx, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + * + */ + +#include +#include +#include + +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +#else +#define _IEEE 1 +#define infnan(x) (0.0) +#endif + +static double const invsqrtpi= 5.641895835477562869480794515607725858441e-0001; +static double const two = 2.0; +static double const zero = 0.0; +static double const one = 1.0; + +double +jn(int n, double x) +{ + int i; + int sgn; + double a; + double b; + double temp; + double z; + double w; + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + /* if J(n,NaN) is NaN */ + if (_IEEE && isnan(x)) return x+x; + if (n<0){ + n = -n; + x = -x; + } + if (n==0) return(j0(x)); + if (n==1) return(j1(x)); + sgn = (n&1)&(x < zero); /* even n -- 0, odd n -- sign(x) */ + x = fabs(x); + if (x == 0 || !finite (x)) { /* if x is 0 or inf */ + b = zero; + } else if ((double) n <= x) { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if (_IEEE && x >= 8.148143905337944345e+090) { + /* x >= 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch(n&3) { + case 0: temp = cos(x)+sin(x); break; + case 1: temp = -cos(x)+sin(x); break; + case 2: temp = -cos(x)-sin(x); break; + case 3: temp = cos(x)-sin(x); break; + default: temp = 0; /* keep the stupid compiler silent */ + } + b = invsqrtpi*temp/sqrt(x); + } else { + a = j0(x); + b = j1(x); + for(i=1;i 33) /* underflow */ + b = zero; + else { + temp = x*0.5; b = temp; + for (a=one,i=2;i<=n;i++) { + a *= (double)i; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + } + b = b/a; + } + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + double t,v; + double q0,q1,h,tmp; int k,m; + w = (n+n)/(double)x; h = 2.0/(double)x; + q0 = w; z = w+h; q1 = w*z - 1.0; k=1; + while (q1<1.0e9) { + k += 1; z += h; + tmp = z*q1 - q0; + q0 = q1; + q1 = tmp; + } + m = n+n; + for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); + a = t; + b = one; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result will + * likely underflow to zero + */ + tmp = n; + v = two/x; + tmp = tmp*log(fabs(v*tmp)); + for (i=n-1;i>0;i--){ + temp = b; + b = ((i+i)/x)*b - a; + a = temp; + /* scale b to avoid spurious overflow */ +# if defined(vax) || defined(tahoe) +# define BMAX 1e13 +# else +# define BMAX 1e100 +# endif /* defined(vax) || defined(tahoe) */ + if (b > BMAX) { + a /= b; + t /= b; + b = one; + } + } + b = (t*j0(x)/b); + } + } + return ((sgn == 1) ? -b : b); +} + +double +yn(int n, double x) +{ + int i; + int sign; + double a; + double b; + double temp; + + /* Y(n,NaN), Y(n, x < 0) is NaN */ + if (x <= 0 || (_IEEE && x != x)) { + if (_IEEE && x < 0) return zero/zero; + else if (x < 0) return (infnan(EDOM)); + else if (_IEEE) return -one/zero; + else return(infnan(-ERANGE)); + } else if (!finite(x)) { + return(0); + } + sign = 1; + if (n<0){ + n = -n; + sign = 1 - ((n&1)<<2); + } + if (n == 0) return(y0(x)); + if (n == 1) return(sign*y1(x)); + if(_IEEE && x >= 8.148143905337944345e+090) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch (n&3) { + case 0: temp = sin(x)-cos(x); break; + case 1: temp = -sin(x)-cos(x); break; + case 2: temp = -sin(x)+cos(x); break; + case 3: temp = sin(x)+cos(x); break; + default: temp = 0; /* keep the stupid compiler silent */ + } + b = invsqrtpi*temp/sqrt(x); + } else { + a = y0(x); + b = y1(x); + /* quit if b is -inf */ + for (i = 1; i < n && !finite(b); i++){ + temp = b; + b = ((double)(i+i)/x)*b - a; + a = temp; + } + } + if (!_IEEE && !finite(b)) + return (infnan(-sign * ERANGE)); + return ((sign > 0) ? b : -b); +} diff --git a/src/kernel/libroot/posix/math/lgamma.c b/src/kernel/libroot/posix/math/lgamma.c new file mode 100644 index 0000000000..072acf7b09 --- /dev/null +++ b/src/kernel/libroot/posix/math/lgamma.c @@ -0,0 +1,306 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Coded by Peter McIlroy, Nov 1992; + * + * The financial support of UUNET Communications Services is greatfully + * acknowledged. + */ + +#include +#include + +#include "mathimpl.h" + +/* Log gamma function. + * Error: x > 0 error < 1.3ulp. + * x > 4, error < 1ulp. + * x > 9, error < .6ulp. + * x < 0, all bets are off. (When G(x) ~ 1, log(G(x)) ~ 0) + * Method: + * x > 6: + * Use the asymptotic expansion (Stirling's Formula) + * 0 < x < 6: + * Use gamma(x+1) = x*gamma(x) for argument reduction. + * Use rational approximation in + * the range 1.2, 2.5 + * Two approximations are used, one centered at the + * minimum to ensure monotonicity; one centered at 2 + * to maintain small relative error. + * x < 0: + * Use the reflection formula, + * G(1-x)G(x) = PI/sin(PI*x) + * Special values: + * non-positive integer returns +Inf. + * NaN returns NaN +*/ +static int endian; +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +/* double and float have same size exponent field */ +#define TRUNC(x) x = (double) (float) (x) +#else +#define _IEEE 1 +#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000 +#define infnan(x) 0.0 +#endif + +static double small_lgam(double); +static double large_lgam(double); +static double neg_lgam(double); +static /*double zero = 0.0,*/ double one = 1.0; +int signgam; + +#define UNDERFL (1e-1020 * 1e-1020) + +#define LEFT (1.0 - (x0 + .25)) +#define RIGHT (x0 - .218) +/* + * Constants for approximation in [1.244,1.712] +*/ +#define x0 0.461632144968362356785 +#define x0_lo -.000000000000000015522348162858676890521 +#define a0_hi -0.12148629128932952880859 +#define a0_lo .0000000007534799204229502 +#define r0 -2.771227512955130520e-002 +#define r1 -2.980729795228150847e-001 +#define r2 -3.257411333183093394e-001 +#define r3 -1.126814387531706041e-001 +#define r4 -1.129130057170225562e-002 +#define r5 -2.259650588213369095e-005 +#define s0 1.714457160001714442e+000 +#define s1 2.786469504618194648e+000 +#define s2 1.564546365519179805e+000 +#define s3 3.485846389981109850e-001 +#define s4 2.467759345363656348e-002 +/* + * Constants for approximation in [1.71, 2.5] +*/ +#define a1_hi 4.227843350984671344505727574870e-01 +#define a1_lo 4.670126436531227189e-18 +#define p0 3.224670334241133695662995251041e-01 +#define p1 3.569659696950364669021382724168e-01 +#define p2 1.342918716072560025853732668111e-01 +#define p3 1.950702176409779831089963408886e-02 +#define p4 8.546740251667538090796227834289e-04 +#define q0 1.000000000000000444089209850062e+00 +#define q1 1.315850076960161985084596381057e+00 +#define q2 6.274644311862156431658377186977e-01 +#define q3 1.304706631926259297049597307705e-01 +#define q4 1.102815279606722369265536798366e-02 +#define q5 2.512690594856678929537585620579e-04 +#define q6 -1.003597548112371003358107325598e-06 +/* + * Stirling's Formula, adjusted for equal-ripple. x in [6,Inf]. +*/ +#define lns2pi .418938533204672741780329736405 +#define pb0 8.33333333333333148296162562474e-02 +#define pb1 -2.77777777774548123579378966497e-03 +#define pb2 7.93650778754435631476282786423e-04 +#define pb3 -5.95235082566672847950717262222e-04 +#define pb4 8.41428560346653702135821806252e-04 +#define pb5 -1.89773526463879200348872089421e-03 +#define pb6 5.69394463439411649408050664078e-03 +#define pb7 -1.44705562421428915453880392761e-02 + +/* __pure double */ +double +lgamma(double x) +{ + double r; + + signgam = 1; + endian = ((*(int *) &one)) ? 1 : 0; + + if (!finite(x)) { + if (_IEEE) + return (x+x); + else return (infnan(EDOM)); + } + + if (x > 6 + RIGHT) { + r = large_lgam(x); + return (r); + } else if (x > 1e-16) { + return (small_lgam(x)); + } else if (x > -1e-16) { + if (x < 0) + signgam = -1, x = -x; + return (-log(x)); + } else { + return (neg_lgam(x)); + } +} + +static double +large_lgam(double x) +{ + double z, p, x1; + struct Double t, u, v; + u = __log__D(x); + u.a -= 1.0; + if (x > 1e15) { + v.a = x - 0.5; + TRUNC(v.a); + v.b = (x - v.a) - 0.5; + t.a = u.a*v.a; + t.b = x*u.b + v.b*u.a; + if (_IEEE == 0 && !finite(t.a)) + return(infnan(ERANGE)); + return(t.a + t.b); + } + x1 = 1./x; + z = x1*x1; + p = pb0+z*(pb1+z*(pb2+z*(pb3+z*(pb4+z*(pb5+z*(pb6+z*pb7)))))); + /* error in approximation = 2.8e-19 */ + + p = p*x1; /* error < 2.3e-18 absolute */ + /* 0 < p < 1/64 (at x = 5.5) */ + v.a = x = x - 0.5; + TRUNC(v.a); /* truncate v.a to 26 bits. */ + v.b = x - v.a; + t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */ + t.b = v.b*u.a + x*u.b; + t.b += p; t.b += lns2pi; /* return t + lns2pi + p */ + return (t.a + t.b); +} + +static double +small_lgam(double x) +{ + int x_int; + double y, z, t, r = 0, p, q, hi, lo; + struct Double rr; + x_int = (x + .5); + y = x - x_int; + if (x_int <= 2 && y > RIGHT) { + t = y - x0; + y--; x_int++; + goto CONTINUE; + } else if (y < -LEFT) { + t = y +(1.0-x0); +CONTINUE: + z = t - x0_lo; + p = r0+z*(r1+z*(r2+z*(r3+z*(r4+z*r5)))); + q = s0+z*(s1+z*(s2+z*(s3+z*s4))); + r = t*(z*(p/q) - x0_lo); + t = .5*t*t; + z = 1.0; + switch (x_int) { + case 6: z = (y + 5); + case 5: z *= (y + 4); + case 4: z *= (y + 3); + case 3: z *= (y + 2); + rr = __log__D(z); + rr.b += a0_lo; rr.a += a0_hi; + return(((r+rr.b)+t+rr.a)); + case 2: return(((r+a0_lo)+t)+a0_hi); + case 0: r -= log1p(x); + default: rr = __log__D(x); + rr.a -= a0_hi; rr.b -= a0_lo; + return(((r - rr.b) + t) - rr.a); + } + } else { + p = p0+y*(p1+y*(p2+y*(p3+y*p4))); + q = q0+y*(q1+y*(q2+y*(q3+y*(q4+y*(q5+y*q6))))); + p = p*(y/q); + t = (double)(float) y; + z = y-t; + hi = (double)(float) (p+a1_hi); + lo = a1_hi - hi; lo += p; lo += a1_lo; + r = lo*y + z*hi; /* q + r = y*(a0+p/q) */ + q = hi*t; + z = 1.0; + switch (x_int) { + case 6: z = (y + 5); + case 5: z *= (y + 4); + case 4: z *= (y + 3); + case 3: z *= (y + 2); + rr = __log__D(z); + r += rr.b; r += q; + return(rr.a + r); + case 2: return (q+ r); + case 0: rr = __log__D(x); + r -= rr.b; r -= log1p(x); + r += q; r-= rr.a; + return(r); + default: rr = __log__D(x); + r -= rr.b; + q -= rr.a; + return (r+q); + } + } +} + +static double +neg_lgam(double x) +{ + int xi; + double y, z, one = 1.0, zero = 0.0; + extern double gamma(); + + /* avoid destructive cancellation as much as possible */ + if (x > -170) { + xi = x; + if (xi == x) { + if (_IEEE) + return(one/zero); + else + return(infnan(ERANGE)); + } + y = gamma(x); + if (y < 0) + y = -y, signgam = -1; + return (log(y)); + } + z = floor(x + .5); + if (z == x) { /* convention: G(-(integer)) -> +Inf */ + if (_IEEE) + return (one/zero); + else + return (infnan(ERANGE)); + } + y = .5*ceil(x); + if (y == ceil(y)) + signgam = -1; + x = -x; + z = fabs(x + z); /* 0 < z <= .5 */ + if (z < .25) + z = sin(M_PI*z); + else + z = cos(M_PI*(0.5-z)); + z = log(M_PI/(z*x)); + y = large_lgam(x); + return (z - y); +} diff --git a/src/kernel/libroot/posix/math/log.c b/src/kernel/libroot/posix/math/log.c new file mode 100644 index 0000000000..7480b8acbd --- /dev/null +++ b/src/kernel/libroot/posix/math/log.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "mathimpl.h" + +/* Table-driven natural logarithm. + * + * This code was derived, with minor modifications, from: + * Peter Tang, "Table-Driven Implementation of the + * Logarithm in IEEE Floating-Point arithmetic." ACM Trans. + * Math Software, vol 16. no 4, pp 378-400, Dec 1990). + * + * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256, + * where F = j/128 for j an integer in [0, 128]. + * + * log(2^m) = log2_hi*m + log2_tail*m + * since m is an integer, the dominant term is exact. + * m has at most 10 digits (for subnormal numbers), + * and log2_hi has 11 trailing zero bits. + * + * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h + * logF_hi[] + 512 is exact. + * + * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ... + * the leading term is calculated to extra precision in two + * parts, the larger of which adds exactly to the dominant + * m and F terms. + * There are two cases: + * 1. when m, j are non-zero (m | j), use absolute + * precision for the leading term. + * 2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1). + * In this case, use a relative precision of 24 bits. + * (This is done differently in the original paper) + * + * Special cases: + * 0 return signalling -Inf + * neg return signalling NaN + * +Inf return +Inf +*/ + +#if defined(vax) || defined(tahoe) +#define _IEEE 0 +#define TRUNC(x) x = (double) (float) (x) +#else +#define _IEEE 1 +#define endian (((*(int *) &one)) ? 1 : 0) +#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000 +#define infnan(x) 0.0 +#endif + +#define N 128 + +/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128. + * Used for generation of extend precision logarithms. + * The constant 35184372088832 is 2^45, so the divide is exact. + * It ensures correct reading of logF_head, even for inaccurate + * decimal-to-binary conversion routines. (Everybody gets the + * right answer for integers less than 2^53.) + * Values for log(F) were generated using error < 10^-57 absolute + * with the bc -l package. +*/ +static double const A1 = .08333333333333178827; +static double const A2 = .01250000000377174923; +static double const A3 = .002232139987919447809; +static double const A4 = .0004348877777076145742; + +static double const logF_head[N+1] = { + 0., + .007782140442060381246, + .015504186535963526694, + .023167059281547608406, + .030771658666765233647, + .038318864302141264488, + .045809536031242714670, + .053244514518837604555, + .060624621816486978786, + .067950661908525944454, + .075223421237524235039, + .082443669210988446138, + .089612158689760690322, + .096729626458454731618, + .103796793681567578460, + .110814366340264314203, + .117783035656430001836, + .124703478501032805070, + .131576357788617315236, + .138402322859292326029, + .145182009844575077295, + .151916042025732167530, + .158605030176659056451, + .165249572895390883786, + .171850256926518341060, + .178407657472689606947, + .184922338493834104156, + .191394852999565046047, + .197825743329758552135, + .204215541428766300668, + .210564769107350002741, + .216873938300523150246, + .223143551314024080056, + .229374101064877322642, + .235566071312860003672, + .241719936886966024758, + .247836163904594286577, + .253915209980732470285, + .259957524436686071567, + .265963548496984003577, + .271933715484010463114, + .277868451003087102435, + .283768173130738432519, + .289633292582948342896, + .295464212893421063199, + .301261330578199704177, + .307025035294827830512, + .312755710004239517729, + .318453731118097493890, + .324119468654316733591, + .329753286372579168528, + .335355541920762334484, + .340926586970454081892, + .346466767346100823488, + .351976423156884266063, + .357455888922231679316, + .362905493689140712376, + .368325561158599157352, + .373716409793814818840, + .379078352934811846353, + .384411698910298582632, + .389716751140440464951, + .394993808240542421117, + .400243164127459749579, + .405465108107819105498, + .410659924985338875558, + .415827895143593195825, + .420969294644237379543, + .426084395310681429691, + .431173464818130014464, + .436236766774527495726, + .441274560805140936281, + .446287102628048160113, + .451274644139630254358, + .456237433481874177232, + .461175715122408291790, + .466089729924533457960, + .470979715219073113985, + .475845904869856894947, + .480688529345570714212, + .485507815781602403149, + .490303988045525329653, + .495077266798034543171, + .499827869556611403822, + .504556010751912253908, + .509261901790523552335, + .513945751101346104405, + .518607764208354637958, + .523248143765158602036, + .527867089620485785417, + .532464798869114019908, + .537041465897345915436, + .541597282432121573947, + .546132437597407260909, + .550647117952394182793, + .555141507540611200965, + .559615787935399566777, + .564070138285387656651, + .568504735352689749561, + .572919753562018740922, + .577315365035246941260, + .581691739635061821900, + .586049045003164792433, + .590387446602107957005, + .594707107746216934174, + .599008189645246602594, + .603290851438941899687, + .607555250224322662688, + .611801541106615331955, + .616029877215623855590, + .620240409751204424537, + .624433288012369303032, + .628608659422752680256, + .632766669570628437213, + .636907462236194987781, + .641031179420679109171, + .645137961373620782978, + .649227946625615004450, + .653301272011958644725, + .657358072709030238911, + .661398482245203922502, + .665422632544505177065, + .669430653942981734871, + .673422675212350441142, + .677398823590920073911, + .681359224807238206267, + .685304003098281100392, + .689233281238557538017, + .693147180560117703862 +}; + +static double const logF_tail[N+1] = { + 0., + -.00000000000000543229938420049, + .00000000000000172745674997061, + -.00000000000001323017818229233, + -.00000000000001154527628289872, + -.00000000000000466529469958300, + .00000000000005148849572685810, + -.00000000000002532168943117445, + -.00000000000005213620639136504, + -.00000000000001819506003016881, + .00000000000006329065958724544, + .00000000000008614512936087814, + -.00000000000007355770219435028, + .00000000000009638067658552277, + .00000000000007598636597194141, + .00000000000002579999128306990, + -.00000000000004654729747598444, + -.00000000000007556920687451336, + .00000000000010195735223708472, + -.00000000000017319034406422306, + -.00000000000007718001336828098, + .00000000000010980754099855238, + -.00000000000002047235780046195, + -.00000000000008372091099235912, + .00000000000014088127937111135, + .00000000000012869017157588257, + .00000000000017788850778198106, + .00000000000006440856150696891, + .00000000000016132822667240822, + -.00000000000007540916511956188, + -.00000000000000036507188831790, + .00000000000009120937249914984, + .00000000000018567570959796010, + -.00000000000003149265065191483, + -.00000000000009309459495196889, + .00000000000017914338601329117, + -.00000000000001302979717330866, + .00000000000023097385217586939, + .00000000000023999540484211737, + .00000000000015393776174455408, + -.00000000000036870428315837678, + .00000000000036920375082080089, + -.00000000000009383417223663699, + .00000000000009433398189512690, + .00000000000041481318704258568, + -.00000000000003792316480209314, + .00000000000008403156304792424, + -.00000000000034262934348285429, + .00000000000043712191957429145, + -.00000000000010475750058776541, + -.00000000000011118671389559323, + .00000000000037549577257259853, + .00000000000013912841212197565, + .00000000000010775743037572640, + .00000000000029391859187648000, + -.00000000000042790509060060774, + .00000000000022774076114039555, + .00000000000010849569622967912, + -.00000000000023073801945705758, + .00000000000015761203773969435, + .00000000000003345710269544082, + -.00000000000041525158063436123, + .00000000000032655698896907146, + -.00000000000044704265010452446, + .00000000000034527647952039772, + -.00000000000007048962392109746, + .00000000000011776978751369214, + -.00000000000010774341461609578, + .00000000000021863343293215910, + .00000000000024132639491333131, + .00000000000039057462209830700, + -.00000000000026570679203560751, + .00000000000037135141919592021, + -.00000000000017166921336082431, + -.00000000000028658285157914353, + -.00000000000023812542263446809, + .00000000000006576659768580062, + -.00000000000028210143846181267, + .00000000000010701931762114254, + .00000000000018119346366441110, + .00000000000009840465278232627, + -.00000000000033149150282752542, + -.00000000000018302857356041668, + -.00000000000016207400156744949, + .00000000000048303314949553201, + -.00000000000071560553172382115, + .00000000000088821239518571855, + -.00000000000030900580513238244, + -.00000000000061076551972851496, + .00000000000035659969663347830, + .00000000000035782396591276383, + -.00000000000046226087001544578, + .00000000000062279762917225156, + .00000000000072838947272065741, + .00000000000026809646615211673, + -.00000000000010960825046059278, + .00000000000002311949383800537, + -.00000000000058469058005299247, + -.00000000000002103748251144494, + -.00000000000023323182945587408, + -.00000000000042333694288141916, + -.00000000000043933937969737844, + .00000000000041341647073835565, + .00000000000006841763641591466, + .00000000000047585534004430641, + .00000000000083679678674757695, + -.00000000000085763734646658640, + .00000000000021913281229340092, + -.00000000000062242842536431148, + -.00000000000010983594325438430, + .00000000000065310431377633651, + -.00000000000047580199021710769, + -.00000000000037854251265457040, + .00000000000040939233218678664, + .00000000000087424383914858291, + .00000000000025218188456842882, + -.00000000000003608131360422557, + -.00000000000050518555924280902, + .00000000000078699403323355317, + -.00000000000067020876961949060, + .00000000000016108575753932458, + .00000000000058527188436251509, + -.00000000000035246757297904791, + -.00000000000018372084495629058, + .00000000000088606689813494916, + .00000000000066486268071468700, + .00000000000063831615170646519, + .00000000000025144230728376072, + -.00000000000017239444525614834 +}; + +double +log(double x) +{ + int m, j; + double F; + double f; + double g; + double q; + double u; + double u2; + double v; + static double const zero = 0.0; + static double const one = 1.0; + volatile double u1; + + /* Catch special cases */ + if (x <= 0) { + if (_IEEE && x == zero) /* log(0) = -Inf */ + return (-one/zero); + else if (_IEEE) /* log(neg) = NaN */ + return (zero/zero); + else if (x == zero) /* NOT REACHED IF _IEEE */ + return (infnan(-ERANGE)); + else + return (infnan(EDOM)); + } else if (!finite(x)) { + if (_IEEE) /* x = NaN, Inf */ + return (x+x); + else + return (infnan(ERANGE)); + } + + /* Argument reduction: 1 <= g < 2; x/2^m = g; */ + /* y = F*(1 + f/F) for |f| <= 2^-8 */ + + m = logb(x); + g = ldexp(x, -m); + if (_IEEE && m == -1022) { + j = logb(g), m += j; + g = ldexp(g, -j); + } + j = N*(g-1) + .5; + F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */ + f = g - F; + + /* Approximate expansion for log(1+f/F) ~= u + q */ + g = 1/(2*F+f); + u = 2*f*g; + v = u*u; + q = u*v*(A1 + v*(A2 + v*(A3 + v*A4))); + + /* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8, + * u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits. + * It also adds exactly to |m*log2_hi + log_F_head[j] | < 750 + */ + if (m | j) + u1 = u + 513, u1 -= 513; + + /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero; + * u1 = u to 24 bits. + */ + else + u1 = u, TRUNC(u1); + u2 = (2.0*(f - F*u1) - u1*f) * g; + /* u1 + u2 = 2f/(2F+f) to extra precision. */ + + /* log(x) = log(2^m*F*(1+f/F)) = */ + /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */ + /* (exact) + (tiny) */ + + u1 += m*logF_head[N] + logF_head[j]; /* exact */ + u2 = (u2 + logF_tail[j]) + q; /* tiny */ + u2 += logF_tail[N]*m; + return (u1 + u2); +} + +/* + * Extra precision variant, returning struct {double a, b;}; + * log(x) = a+b to 63 bits, with a is rounded to 26 bits. + */ +struct Double +__log__D(double x) +{ + int m; + int j; + double F; + double f; + double g; + double q; + double u; + double v; + double u2; + static double const one = 1.0; + volatile double u1; + struct Double r; + + /* Argument reduction: 1 <= g < 2; x/2^m = g; */ + /* y = F*(1 + f/F) for |f| <= 2^-8 */ + + m = logb(x); + g = ldexp(x, -m); + if (_IEEE && m == -1022) { + j = logb(g), m += j; + g = ldexp(g, -j); + } + j = N*(g-1) + .5; + F = (1.0/N) * j + 1; + f = g - F; + + g = 1/(2*F+f); + u = 2*f*g; + v = u*u; + q = u*v*(A1 + v*(A2 + v*(A3 + v*A4))); + if (m | j) + u1 = u + 513, u1 -= 513; + else + u1 = u, TRUNC(u1); + u2 = (2.0*(f - F*u1) - u1*f) * g; + + u1 += m*logF_head[N] + logF_head[j]; + + u2 += logF_tail[j]; u2 += q; + u2 += logF_tail[N]*m; + r.a = u1 + u2; /* Only difference is here */ + TRUNC(r.a); + r.b = (u1 - r.a) + u2; + return (r); +} diff --git a/src/kernel/libroot/posix/math/log10.c b/src/kernel/libroot/posix/math/log10.c new file mode 100644 index 0000000000..f88acccb1d --- /dev/null +++ b/src/kernel/libroot/posix/math/log10.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* LOG10(X) + * RETURN THE BASE 10 LOGARITHM OF x + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/20/85; + * REVISED BY K.C. NG on 1/23/85, 3/7/85, 4/16/85. + * + * Required kernel function: + * log(x) + * + * Method : + * log(x) + * log10(x) = --------- or [1/log(10)]*log(x) + * log(10) + * + * Note: + * [log(10)] rounded to 56 bits has error .0895 ulps, + * [1/log(10)] rounded to 53 bits has error .198 ulps; + * therefore, for better accuracy, in VAX D format, we divide + * log(x) by log(10), but in IEEE Double format, we multiply + * log(x) by [1/log(10)]. + * + * Special cases: + * log10(x) is NaN with signal if x < 0; + * log10(+INF) is +INF with no signal; log10(0) is -INF with signal; + * log10(NaN) is that NaN with no signal. + * + * Accuracy: + * log10(X) returns the exact log10(x) nearly rounded. In a test run + * with 1,536,000 random arguments on a VAX, the maximum observed + * error was 1.74 ulps (units in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(ln10hi, 2.3025850929940456790E0 ,5d8d,4113,a8ac,ddaa, 2, .935D8DDDAAA8AC) + +ic(ivln10, 4.3429448190325181667E-1, -2, 1.BCB7B1526E50E) + +#ifdef vccast +#define ln10hi vccast(ln10hi) +#endif + + +double log10(x) +double x; +{ +#if defined(vax)||defined(tahoe) + return(log(x)/ln10hi); +#else /* defined(vax)||defined(tahoe) */ + return(ivln10*log(x)); +#endif /* defined(vax)||defined(tahoe) */ +} diff --git a/src/kernel/libroot/posix/math/log1p.c b/src/kernel/libroot/posix/math/log1p.c new file mode 100644 index 0000000000..5fa013f53f --- /dev/null +++ b/src/kernel/libroot/posix/math/log1p.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* LOG1P(x) + * RETURN THE LOGARITHM OF 1+x + * DOUBLE PRECISION (VAX D FORMAT 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/19/85; + * REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/24/85, 4/16/85. + * + * Required system supported functions: + * scalb(x,n) + * copysign(x,y) + * logb(x) + * finite(x) + * + * Required kernel function: + * log__L(z) + * + * Method : + * 1. Argument Reduction: find k and f such that + * 1+x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * log(1+f) is computed by + * + * log(1+f) = 2s + s*log__L(s*s) + * where + * log__L(z) = z*(L1 + z*(L2 + z*(... (L6 + z*L7)...))) + * + * See log__L() for the values of the coefficients. + * + * 3. Finally, log(1+x) = k*ln2 + log(1+f). + * + * Remarks 1. In step 3 n*ln2 will be stored in two floating point numbers + * n*ln2hi + n*ln2lo, where ln2hi is chosen such that the last + * 20 bits (for VAX D format), or the last 21 bits ( for IEEE + * double) is 0. This ensures n*ln2hi is exactly representable. + * 2. In step 1, f may not be representable. A correction term c + * for f is computed. It follows that the correction term for + * f - t (the leading term of log(1+f) in step 2) is c-c*x. We + * add this correction term to n*ln2lo to attenuate the error. + * + * + * Special cases: + * log1p(x) is NaN with signal if x < -1; log1p(NaN) is NaN with no signal; + * log1p(INF) is +INF; log1p(-1) is -INF with signal; + * only log1p(0)=0 is exact for finite argument. + * + * Accuracy: + * log1p(x) returns the exact log(1+x) nearly rounded. In a test run + * with 1,536,000 random arguments on a VAX, the maximum observed + * error was .846 ulps (units in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include +#include "mathimpl.h" + +vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000) +vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC) +vc(sqrt2, 1.4142135623730950622E0 ,04f3,40b5,de65,33f9, 1, .B504F333F9DE65) + +ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000) +ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76) +ic(sqrt2, 1.4142135623730951455E0, 0, 1.6A09E667F3BCD) + +#ifdef vccast +#define ln2hi vccast(ln2hi) +#define ln2lo vccast(ln2lo) +#define sqrt2 vccast(sqrt2) +#endif + +double log1p(x) +double x; +{ + static double const zero=0.0; + static double const negone= -1.0; + static double const one=1.0; + static double const half=1.0/2.0; + static double const small=1.0E-20; /* 1+small == 1 */ + double z; + double s; + double t; + double c; + int k; + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + + if(finite(x)) { + if( x > negone ) { + + /* argument reduction */ + if(copysign(x,one)= sqrt2 ) + { k += 1 ; z *= half; t *= half; } + t += negone; x = z + t; + c = (t-x)+z ; /* correction term for x */ + + /* compute log(1+x) */ + s = x/(2+x); t = x*x*half; + c += (k*ln2lo-c*x); + z = c+s*(t+__log__L(s*s)); + x += (z - t) ; + + return(k*ln2hi+x); + } + /* end of if (x > negone) */ + + else { +#if defined(vax)||defined(tahoe) + if ( x == negone ) + return (infnan(-ERANGE)); /* -INF */ + else + return (infnan(EDOM)); /* NaN */ +#else /* defined(vax)||defined(tahoe) */ + /* x = -1, return -INF with signal */ + if ( x == negone ) return( negone/zero ); + + /* negative argument for log, return NaN with signal */ + else return ( zero / zero ); +#endif /* defined(vax)||defined(tahoe) */ + } + } + /* end of if (finite(x)) */ + + /* log(-INF) is NaN */ + else if(x<0) + return(zero/zero); + + /* log(+INF) is INF */ + else return(x); +} diff --git a/src/kernel/libroot/posix/math/log__L.c b/src/kernel/libroot/posix/math/log__L.c new file mode 100644 index 0000000000..105140a0b8 --- /dev/null +++ b/src/kernel/libroot/posix/math/log__L.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* log__L(Z) + * LOG(1+X) - 2S X + * RETURN --------------- WHERE Z = S*S, S = ------- , 0 <= Z <= .0294... + * S 2 + X + * + * DOUBLE PRECISION (VAX D FORMAT 56 bits or IEEE DOUBLE 53 BITS) + * KERNEL FUNCTION FOR LOG; TO BE USED IN LOG1P, LOG, AND POW FUNCTIONS + * CODED IN C BY K.C. NG, 1/19/85; + * REVISED BY K.C. Ng, 2/3/85, 4/16/85. + * + * Method : + * 1. Polynomial approximation: let s = x/(2+x). + * Based on log(1+x) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * + * (log(1+x) - 2s)/s is computed by + * + * z*(L1 + z*(L2 + z*(... (L7 + z*L8)...))) + * + * where z=s*s. (See the listing below for Lk's values.) The + * coefficients are obtained by a special Remez algorithm. + * + * Accuracy: + * Assuming no rounding error, the maximum magnitude of the approximation + * error (absolute) is 2**(-58.49) for IEEE double, and 2**(-63.63) + * for VAX D format. + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(L1, 6.6666666666666703212E-1 ,aaaa,402a,aac5,aaaa, 0, .AAAAAAAAAAAAC5) +vc(L2, 3.9999999999970461961E-1 ,cccc,3fcc,2684,cccc, -1, .CCCCCCCCCC2684) +vc(L3, 2.8571428579395698188E-1 ,4924,3f92,5782,92f8, -1, .92492492F85782) +vc(L4, 2.2222221233634724402E-1 ,8e38,3f63,af2c,39b7, -2, .E38E3839B7AF2C) +vc(L5, 1.8181879517064680057E-1 ,2eb4,3f3a,655e,cc39, -2, .BA2EB4CC39655E) +vc(L6, 1.5382888777946145467E-1 ,8551,3f1d,781d,e8c5, -2, .9D8551E8C5781D) +vc(L7, 1.3338356561139403517E-1 ,95b3,3f08,cd92,907f, -2, .8895B3907FCD92) +vc(L8, 1.2500000000000000000E-1 ,0000,3f00,0000,0000, -2, .80000000000000) + +ic(L1, 6.6666666666667340202E-1, -1, 1.5555555555592) +ic(L2, 3.9999999999416702146E-1, -2, 1.999999997FF24) +ic(L3, 2.8571428742008753154E-1, -2, 1.24924941E07B4) +ic(L4, 2.2222198607186277597E-1, -3, 1.C71C52150BEA6) +ic(L5, 1.8183562745289935658E-1, -3, 1.74663CC94342F) +ic(L6, 1.5314087275331442206E-1, -3, 1.39A1EC014045B) +ic(L7, 1.4795612545334174692E-1, -3, 1.2F039F0085122) + +#ifdef vccast +#define L1 vccast(L1) +#define L2 vccast(L2) +#define L3 vccast(L3) +#define L4 vccast(L4) +#define L5 vccast(L5) +#define L6 vccast(L6) +#define L7 vccast(L7) +#define L8 vccast(L8) +#endif + +double __log__L(z) +double z; +{ +#if defined(vax)||defined(tahoe) + return(z*(L1+z*(L2+z*(L3+z*(L4+z*(L5+z*(L6+z*(L7+z*L8)))))))); +#else /* defined(vax)||defined(tahoe) */ + return(z*(L1+z*(L2+z*(L3+z*(L4+z*(L5+z*(L6+z*L7))))))); +#endif /* defined(vax)||defined(tahoe) */ +} diff --git a/src/kernel/libroot/posix/math/pow.c b/src/kernel/libroot/posix/math/pow.c new file mode 100644 index 0000000000..8991f55134 --- /dev/null +++ b/src/kernel/libroot/posix/math/pow.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* POW(X,Y) + * RETURN X**Y + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/8/85; + * REVISED BY K.C. NG on 7/10/85. + * KERNEL pow_P() REPLACED BY P. McILROY 7/22/92. + * Required system supported functions: + * scalb(x,n) + * logb(x) + * copysign(x,y) + * finite(x) + * drem(x,y) + * + * Required kernel functions: + * exp__D(a,c) exp(a + c) for |a| << |c| + * struct d_double dlog(x) r.a + r.b, |r.b| < |r.a| + * + * Method + * 1. Compute and return log(x) in three pieces: + * log(x) = n*ln2 + hi + lo, + * where n is an integer. + * 2. Perform y*log(x) by simulating muti-precision arithmetic and + * return the answer in three pieces: + * y*log(x) = m*ln2 + hi + lo, + * where m is an integer. + * 3. Return x**y = exp(y*log(x)) + * = 2^m * ( exp(hi+lo) ). + * + * Special cases: + * (anything) ** 0 is 1 ; + * (anything) ** 1 is itself; + * (anything) ** NaN is NaN; + * NaN ** (anything except 0) is NaN; + * +(anything > 1) ** +INF is +INF; + * -(anything > 1) ** +INF is NaN; + * +-(anything > 1) ** -INF is +0; + * +-(anything < 1) ** +INF is +0; + * +(anything < 1) ** -INF is +INF; + * -(anything < 1) ** -INF is NaN; + * +-1 ** +-INF is NaN and signal INVALID; + * +0 ** +(anything except 0, NaN) is +0; + * -0 ** +(anything except 0, NaN, odd integer) is +0; + * +0 ** -(anything except 0, NaN) is +INF and signal DIV-BY-ZERO; + * -0 ** -(anything except 0, NaN, odd integer) is +INF with signal; + * -0 ** (odd integer) = -( +0 ** (odd integer) ); + * +INF ** +(anything except 0,NaN) is +INF; + * +INF ** -(anything except 0,NaN) is +0; + * -INF ** (odd integer) = -( +INF ** (odd integer) ); + * -INF ** (even integer) = ( +INF ** (even integer) ); + * -INF ** -(anything except integer,NaN) is NaN with signal; + * -(x=anything) ** (k=integer) is (-1)**k * (x ** k); + * -(anything except 0) ** (non-integer) is NaN with signal; + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular, on a SUN, a VAX, + * and a Zilog Z8000, + * pow(integer,integer) + * always returns the correct integer provided it is representable. + * In a test run with 100,000 random arguments with 0 < x, y < 20.0 + * on a VAX, the maximum observed error was 1.79 ulps (units in the + * last place). + * + * Constants : + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include +#include + +#include "mathimpl.h" + +#if (defined(vax) || defined(tahoe)) +#define TRUNC(x) x = (double) (float) x +#define _IEEE 0 +#else +#define _IEEE 1 +#define endian (((*(int *) &one)) ? 1 : 0) +#define TRUNC(x) *(((int *) &x)+endian) &= 0xf8000000 +#define infnan(x) 0.0 +#endif /* vax or tahoe */ + +static double const zero=0.0; +static double const one=1.0; +static double const two=2.0; +static double const negone= -1.0; + +static double pow_P(double, double); + +double +pow(double x, double y) +{ + double t; + if (y==zero) + return (one); + else if (y==one || (_IEEE && x != x)) + return (x); /* if x is NaN or y=1 */ + else if (_IEEE && y!=y) /* if y is NaN */ + return (y); + else if (!finite(y)) /* if y is INF */ + if ((t=fabs(x))==one) /* +-1 ** +-INF is NaN */ + return (y - y); + else if (t>one) + return ((y<0)? zero : ((x0)? zero : ((x<0)? y-y : -y)); + else if (y==two) + return (x*x); + else if (y==negone) + return (one/x); + /* x > 0, x == +0 */ + else if (copysign(one, x) == one) + return (pow_P(x, y)); + + /* sign(x)= -1 */ + /* if y is an even integer */ + else if ( (t=drem(y,two)) == zero) + return (pow_P(-x, y)); + + /* if y is an odd integer */ + else if (copysign(t,one) == one) + return (-pow_P(-x, y)); + + /* Henceforth y is not an integer */ + else if (x==zero) /* x is -0 */ + return ((y>zero)? -x : one/(-x)); + else if (_IEEE) + return (zero/zero); + else + return (infnan(EDOM)); +} +/* kernel function for x >= 0 */ +static +double +pow_P(double x, double y) +{ + struct Double s, t, __log__D(); + double __exp__D(); + volatile double huge = 1e300, tiny = 1e-300; + + if (x == zero) { + if (y > zero) + return (zero); + else if (_IEEE) + return (huge*huge); + else + return (infnan(ERANGE)); + } + if (x == one) + return (one); + if (!finite(x)) { + if (y < zero) + return (zero); + else if (_IEEE) + return (huge*huge); + else + return (infnan(ERANGE)); + } + if (y >= 7e18) { /* infinity */ + if (x < 1) + return(tiny*tiny); + else if (_IEEE) + return (huge*huge); + else + return (infnan(ERANGE)); + } + + /* Return exp(y*log(x)), using simulated extended */ + /* precision for the log and the multiply. */ + + s = __log__D(x); + t.a = y; + TRUNC(t.a); + t.b = y - t.a; + t.b = s.b*y + t.b*s.a; + t.a *= s.a; + s.a = t.a + t.b; + s.b = (t.a - s.a) + t.b; + return (__exp__D(s.a, s.b)); +} diff --git a/src/kernel/libroot/posix/math/sincos.c b/src/kernel/libroot/posix/math/sincos.c new file mode 100644 index 0000000000..c3d7ba5dcd --- /dev/null +++ b/src/kernel/libroot/posix/math/sincos.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "trig.h" +double +sin(double x) +{ + double a,c,z; + + if(!finite(x)) /* sin(NaN) and sin(INF) must be NaN */ + return x-x; + x=drem(x,PI2); /* reduce x into [-PI,PI] */ + a=copysign(x,one); + if (a >= PIo4) { + if(a >= PI3o4) /* ... in [3PI/4,PI] */ + x = copysign((a = PI-a),x); + else { /* ... in [PI/4,3PI/4] */ + a = PIo2-a; /* rtn. sign(x)*C(PI/2-|x|) */ + z = a*a; + c = cos__C(z); + z *= half; + a = (z >= thresh ? half-((z-half)-c) : one-(z-c)); + return copysign(a,x); + } + } + + if (a < small) { /* rtn. S(x) */ + (void volatile)(big+a); + return x; + } + return x+x*sin__S(x*x); +} + +double +cos(double x) +{ + double a,c,z,s = 1.0; + + if(!finite(x)) /* cos(NaN) and cos(INF) must be NaN */ + return x-x; + x=drem(x,PI2); /* reduce x into [-PI,PI] */ + a=copysign(x,one); + if (a >= PIo4) { + if (a >= PI3o4) { /* ... in [3PI/4,PI] */ + a = PI-a; + s = negone; + } + else { /* ... in [PI/4,3PI/4] */ + a = PIo2-a; + return a+a*sin__S(a*a); /* rtn. S(PI/2-|x|) */ + } + } + if (a < small) { + (void volatile)(big+a); + return s; /* rtn. s*C(a) */ + } + z = a*a; + c = cos__C(z); + z *= half; + a = (z >= thresh ? half-((z-half)-c) : one-(z-c)); + return copysign(a,s); +} diff --git a/src/kernel/libroot/posix/math/sinh.c b/src/kernel/libroot/posix/math/sinh.c new file mode 100644 index 0000000000..3060eee13f --- /dev/null +++ b/src/kernel/libroot/posix/math/sinh.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* SINH(X) + * RETURN THE HYPERBOLIC SINE OF X + * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/8/85; + * REVISED BY K.C. NG on 2/8/85, 3/7/85, 3/24/85, 4/16/85. + * + * Required system supported functions : + * copysign(x,y) + * scalb(x,N) + * + * Required kernel functions: + * expm1(x) ...return exp(x)-1 + * + * Method : + * 1. reduce x to non-negative by sinh(-x) = - sinh(x). + * 2. + * + * expm1(x) + expm1(x)/(expm1(x)+1) + * 0 <= x <= lnovfl : sinh(x) := -------------------------------- + * 2 + * lnovfl <= x <= lnovfl+ln2 : sinh(x) := expm1(x)/2 (avoid overflow) + * lnovfl+ln2 < x < INF : overflow to INF + * + * + * Special cases: + * sinh(x) is x if x is +INF, -INF, or NaN. + * only sinh(0)=0 is exact for finite argument. + * + * Accuracy: + * sinh(x) returns the exact hyperbolic sine of x nearly rounded. In + * a test run with 1,024,000 random arguments on a VAX, the maximum + * observed error was 1.93 ulps (units in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "mathimpl.h" + +vc(mln2hi, 8.8029691931113054792E1 ,0f33,43b0,2bdb,c7e2, 7, .B00F33C7E22BDB) +vc(mln2lo,-4.9650192275318476525E-16 ,1b60,a70f,582a,279e, -50,-.8F1B60279E582A) +vc(lnovfl, 8.8029691931113053016E1 ,0f33,43b0,2bda,c7e2, 7, .B00F33C7E22BDA) + +ic(mln2hi, 7.0978271289338397310E2, 10, 1.62E42FEFA39EF) +ic(mln2lo, 2.3747039373786107478E-14, -45, 1.ABC9E3B39803F) +ic(lnovfl, 7.0978271289338397310E2, 9, 1.62E42FEFA39EF) + +#ifdef vccast +#define mln2hi vccast(mln2hi) +#define mln2lo vccast(mln2lo) +#define lnovfl vccast(lnovfl) +#endif + +#if defined(vax)||defined(tahoe) +static int max = 126 ; +#else /* defined(vax)||defined(tahoe) */ +static int max = 1023 ; +#endif /* defined(vax)||defined(tahoe) */ + + +double sinh(x) +double x; +{ + static const double one=1.0, half=1.0/2.0 ; + double t, sign; +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + sign=copysign(one,x); + x=copysign(x,one); + if(x= PIo4) { + k = 1; + x = copysign(PIo2-a,x); + } + else { + k = 0; + if (a < small) { + (void volatile)(big+a); + return x; + } + } + z = x*x; + cc = cos__C(z); + ss = sin__S(z); + z *= half; /* Next get c = cos(x) accurately */ + c = (z >= thresh ? half-((z-half)-cc) : one-(z-cc)); + if (k == 0) { + return x+(x*(z-(cc-ss)))/c; /* ... sin/cos */ +#ifdef national + } else if (x == zero) { + return copysign(fmax,x); /* no inf on 32k */ +#endif /* national */ + } else { + return c/(x+x*ss); /* ... cos/sin */ + } +} diff --git a/src/kernel/libroot/posix/math/tanh.c b/src/kernel/libroot/posix/math/tanh.c new file mode 100644 index 0000000000..95d7c4dc82 --- /dev/null +++ b/src/kernel/libroot/posix/math/tanh.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* TANH(X) + * RETURN THE HYPERBOLIC TANGENT OF X + * DOUBLE PRECISION (VAX D FORMAT 56 BITS, IEEE DOUBLE 53 BITS) + * CODED IN C BY K.C. NG, 1/8/85; + * REVISED BY K.C. NG on 2/8/85, 2/11/85, 3/7/85, 3/24/85. + * + * Required system supported functions : + * copysign(x,y) + * finite(x) + * + * Required kernel function: + * expm1(x) ...exp(x)-1 + * + * Method : + * 1. reduce x to non-negative by tanh(-x) = - tanh(x). + * 2. + * 0 < x <= 1.e-10 : tanh(x) := x + * -expm1(-2x) + * 1.e-10 < x <= 1 : tanh(x) := -------------- + * expm1(-2x) + 2 + * 2 + * 1 <= x <= 22.0 : tanh(x) := 1 - --------------- + * expm1(2x) + 2 + * 22.0 < x <= INF : tanh(x) := 1. + * + * Note: 22 was chosen so that fl(1.0+2/(expm1(2*22)+2)) == 1. + * + * Special cases: + * tanh(NaN) is NaN; + * only tanh(0)=0 is exact for finite argument. + * + * Accuracy: + * tanh(x) returns the exact hyperbolic tangent of x nealy rounded. + * In a test run with 1,024,000 random arguments on a VAX, the maximum + * observed error was 2.22 ulps (units in the last place). + */ +#include +#include + +double +tanh(double x) +{ + static double const one=1.0; + static double const two=2.0; + static double const small = 1.0e-10; + static double const big = 1.0e10; + double t; + double sign; + +#if !defined(vax)&&!defined(tahoe) + if(x!=x) return(x); /* x is NaN */ +#endif /* !defined(vax)&&!defined(tahoe) */ + + sign=copysign(one,x); + x=copysign(x,one); + if(x < 22.0) + if( x > one ) + return(copysign(one-two/(expm1(x+x)+two),sign)); + else if ( x > small ) + {t= -expm1(-(x+x)); return(copysign(t/(two-t),sign));} + else /* raise the INEXACT flag for non-zero x */ + {(void volatile)(big+x); return(copysign(x,sign));} + else if(finite(x)) + return (sign+1.0E-37); /* raise the INEXACT flag */ + else + return(sign); /* x is +- INF */ +} diff --git a/src/kernel/libroot/posix/rlimit.c b/src/kernel/libroot/posix/rlimit.c new file mode 100644 index 0000000000..086ef99c7b --- /dev/null +++ b/src/kernel/libroot/posix/rlimit.c @@ -0,0 +1,35 @@ +/* +** Copyright 2002, Jeff Hamilton. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +getrlimit(int resource, struct rlimit *rlp) +{ + int status = sys_getrlimit(resource, rlp); + + RETURN_AND_SET_ERRNO(status); +} + + +int +setrlimit(int resource, const struct rlimit *rlp) +{ + int status = sys_setrlimit(resource, rlp); + + RETURN_AND_SET_ERRNO(status); +} diff --git a/src/kernel/libroot/posix/stdio/Jamfile b/src/kernel/libroot/posix/stdio/Jamfile new file mode 100644 index 0000000000..c222cfc098 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/Jamfile @@ -0,0 +1,48 @@ +SubDir OBOS_TOP src kernel libroot posix stdio ; + +KernelObjects + <$(SOURCE_GRIST)>fclose.c + <$(SOURCE_GRIST)>feof.c + <$(SOURCE_GRIST)>fflush.c + <$(SOURCE_GRIST)>fgetc.c + <$(SOURCE_GRIST)>fgetln.c + <$(SOURCE_GRIST)>fgets.c + <$(SOURCE_GRIST)>findfp.c + <$(SOURCE_GRIST)>flags.c + <$(SOURCE_GRIST)>flockfile.c + <$(SOURCE_GRIST)>fopen.c + <$(SOURCE_GRIST)>fprintf.c + <$(SOURCE_GRIST)>fputc.c + <$(SOURCE_GRIST)>fputs.c + <$(SOURCE_GRIST)>fread.c + <$(SOURCE_GRIST)>fseek.c + <$(SOURCE_GRIST)>fwrite.c + <$(SOURCE_GRIST)>fvwrite.c + <$(SOURCE_GRIST)>fwalk.c + <$(SOURCE_GRIST)>getc.c + <$(SOURCE_GRIST)>getchar.c + <$(SOURCE_GRIST)>gets.c + <$(SOURCE_GRIST)>getw.c + <$(SOURCE_GRIST)>kvsprintf.c + <$(SOURCE_GRIST)>makebuf.c + <$(SOURCE_GRIST)>printf.c + <$(SOURCE_GRIST)>putc.c + <$(SOURCE_GRIST)>putchar.c + <$(SOURCE_GRIST)>puts.c + <$(SOURCE_GRIST)>putw.c + <$(SOURCE_GRIST)>refill.c + <$(SOURCE_GRIST)>rewind.c + <$(SOURCE_GRIST)>rget.c + <$(SOURCE_GRIST)>sscanf.c + <$(SOURCE_GRIST)>sprintf.c + <$(SOURCE_GRIST)>stdio.c + <$(SOURCE_GRIST)>ungetc.c + <$(SOURCE_GRIST)>vfprintf.c + <$(SOURCE_GRIST)>vfscanf.c + <$(SOURCE_GRIST)>vscanf.c + <$(SOURCE_GRIST)>vsprintf.c + <$(SOURCE_GRIST)>wbuf.c + <$(SOURCE_GRIST)>wsetup.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/stdio/fclose.c b/src/kernel/libroot/posix/stdio/fclose.c new file mode 100644 index 0000000000..b2a0567ec1 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fclose.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fclose.c,v 1.2 1996/08/19 08:32:19 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include "local.h" + +int +fclose(fp) + register FILE *fp; +{ + register int r; + + if (fp->_flags == 0) { /* not open! */ + errno = EBADF; + return (EOF); + } + r = fp->_flags & __SWR ? __sflush(fp) : 0; + if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) + r = EOF; + if (fp->_flags & __SMBF) + free((char *)fp->_bf._base); + if (HASUB(fp)) + FREEUB(fp); + if (HASLB(fp)) + FREELB(fp); + fp->_flags = 0; /* Release this FILE for reuse. */ + fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ + return (r); +} diff --git a/src/kernel/libroot/posix/stdio/feof.c b/src/kernel/libroot/posix/stdio/feof.c new file mode 100644 index 0000000000..2186465fc7 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/feof.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: feof.c,v 1.2 1996/08/19 08:32:22 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +/* + * A subroutine version of the macro feof. + */ +#undef feof + +int +feof(fp) + FILE *fp; +{ + return (__sfeof(fp)); +} diff --git a/src/kernel/libroot/posix/stdio/fflush.c b/src/kernel/libroot/posix/stdio/fflush.c new file mode 100644 index 0000000000..e2fe1bfd10 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fflush.c @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fflush.c,v 1.2 1996/08/19 08:32:26 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "local.h" + +/* Flush a single file, or (if fp is NULL) all files. */ +int +fflush(fp) + register FILE *fp; +{ + if (fp == NULL) + return (_fwalk(__sflush)); + if ((fp->_flags & (__SWR | __SRW)) == 0) { + errno = EBADF; + return (EOF); + } + return (__sflush(fp)); +} + +int +__sflush(fp) + register FILE *fp; +{ + register unsigned char *p; + register int n, t; + + t = fp->_flags; + if ((t & __SWR) == 0) + return (0); + + if ((p = fp->_bf._base) == NULL) + return (0); + + n = fp->_p - p; /* write this much */ + + /* + * Set these immediately to avoid problems with longjmp and to allow + * exchange buffering (via setvbuf) in user write function. + */ + fp->_p = p; + fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; + + for (; n > 0; n -= t, p += t) { + t = (*fp->_write)(fp->_cookie, (char *)p, n); + if (t <= 0) { + fp->_flags |= __SERR; + return (EOF); + } + } + return (0); +} diff --git a/src/kernel/libroot/posix/stdio/fgetc.c b/src/kernel/libroot/posix/stdio/fgetc.c new file mode 100644 index 0000000000..4f22603a4b --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fgetc.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fgetc.c,v 1.2 1996/08/19 08:32:27 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +int +fgetc(fp) + FILE *fp; +{ + return (__sgetc(fp)); +} diff --git a/src/kernel/libroot/posix/stdio/fgetln.c b/src/kernel/libroot/posix/stdio/fgetln.c new file mode 100644 index 0000000000..203b5f123c --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fgetln.c @@ -0,0 +1,161 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: fgetln.c,v 1.2 1996/08/19 08:32:29 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include "local.h" + +/* + * Expand the line buffer. Return -1 on error. +#ifdef notdef + * The `new size' does not account for a terminating '\0', + * so we add 1 here. +#endif + */ +static int +__slbexpand(fp, newsize) + FILE *fp; + size_t newsize; +{ + void *p; + +#ifdef notdef + ++newsize; +#endif + if (fp->_lb._size >= newsize) + return (0); + if ((p = realloc(fp->_lb._base, newsize)) == NULL) + return (-1); + fp->_lb._base = p; + fp->_lb._size = newsize; + return (0); +} + +/* + * Get an input line. The returned pointer often (but not always) + * points into a stdio buffer. Fgetline does not alter the text of + * the returned line (which is thus not a C string because it will + * not necessarily end with '\0'), but does allow callers to modify + * it if they wish. Thus, we set __SMOD in case the caller does. + */ +char * +fgetln(fp, lenp) + register FILE *fp; + size_t *lenp; +{ + register unsigned char *p; + register size_t len; + size_t off; + + /* make sure there is input */ + if (fp->_r <= 0 && __srefill(fp)) { + *lenp = 0; + return (NULL); + } + + /* look for a newline in the input */ + if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) { + register char *ret; + + /* + * Found one. Flag buffer as modified to keep fseek from + * `optimising' a backward seek, in case the user stomps on + * the text. + */ + p++; /* advance over it */ + ret = (char *)fp->_p; + *lenp = len = p - fp->_p; + fp->_flags |= __SMOD; + fp->_r -= len; + fp->_p = p; + return (ret); + } + + /* + * We have to copy the current buffered data to the line buffer. + * As a bonus, though, we can leave off the __SMOD. + * + * OPTIMISTIC is length that we (optimistically) expect will + * accomodate the `rest' of the string, on each trip through the + * loop below. + */ +#define OPTIMISTIC 80 + + for (len = fp->_r, off = 0;; len += fp->_r) { + register size_t diff; + + /* + * Make sure there is room for more bytes. Copy data from + * file buffer to line buffer, refill file and look for + * newline. The loop stops only when we find a newline. + */ + if (__slbexpand(fp, len + OPTIMISTIC)) + goto error; + (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, + len - off); + off = len; + if (__srefill(fp)) + break; /* EOF or error: return partial line */ + if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL) + continue; + + /* got it: finish up the line (like code above) */ + p++; + diff = p - fp->_p; + len += diff; + if (__slbexpand(fp, len)) + goto error; + (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, + diff); + fp->_r -= diff; + fp->_p = p; + break; + } + *lenp = len; +#ifdef notdef + fp->_lb._base[len] = 0; +#endif + return ((char *)fp->_lb._base); + +error: + *lenp = 0; /* ??? */ + return (NULL); /* ??? */ +} diff --git a/src/kernel/libroot/posix/stdio/fgetpos.c b/src/kernel/libroot/posix/stdio/fgetpos.c new file mode 100644 index 0000000000..4ea497c7cf --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fgetpos.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fgetpos.c,v 1.3 2000/02/21 22:11:21 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +/* + * fgetpos: like ftello. + */ +int +fgetpos(fp, pos) + FILE *fp; + fpos_t *pos; +{ + return((*pos = ftello(fp)) == (fpos_t)-1); +} diff --git a/src/kernel/libroot/posix/stdio/fgets.c b/src/kernel/libroot/posix/stdio/fgets.c new file mode 100644 index 0000000000..c2bf76f79c --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fgets.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fgets.c,v 1.3 2001/07/09 06:57:44 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "local.h" + +/* + * Read at most n-1 characters from the given file. + * Stop when a newline has been read, or the count runs out. + * Return first argument, or NULL if no characters were read. + */ +char * +fgets(buf, n, fp) + char *buf; + register int n; + register FILE *fp; +{ + register size_t len; + register char *s; + register unsigned char *p, *t; + + if (n <= 0) /* sanity check */ + return (NULL); + + s = buf; + n--; /* leave space for NUL */ + while (n != 0) { + /* + * If the buffer is empty, refill it. + */ + if ((len = fp->_r) <= 0) { + if (__srefill(fp)) { + /* EOF/error: stop with partial or no line */ + if (s == buf) + return (NULL); + break; + } + len = fp->_r; + } + p = fp->_p; + + /* + * Scan through at most n bytes of the current buffer, + * looking for '\n'. If found, copy up to and including + * newline, and stop. Otherwise, copy entire chunk + * and loop. + */ + if (len > n) + len = n; + t = memchr((void *)p, '\n', len); + if (t != NULL) { + len = ++t - p; + fp->_r -= len; + fp->_p = t; + (void)memcpy((void *)s, (void *)p, len); + s[len] = 0; + return (buf); + } + fp->_r -= len; + fp->_p += len; + (void)memcpy((void *)s, (void *)p, len); + s += len; + n -= len; + } + *s = 0; + return (buf); +} diff --git a/src/kernel/libroot/posix/stdio/findfp.c b/src/kernel/libroot/posix/stdio/findfp.c new file mode 100644 index 0000000000..a8575fe199 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/findfp.c @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#include +#include +#include +#include +#include +#include + +#include "local.h" +#include "glue.h" + +/* Prototype needed */ +void f_prealloc(void); + +int __sdidinit; + +/* XXX - these belong in sys/param.h + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is u_int and + * must be cast to any desired pointer type. + */ +#define ALIGNBYTES (sizeof(int) - 1) +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES) + +#define NDYNAMIC 10 /* add ten more whenever necessary */ + +#define std(flags, file) \ + {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite} +/* p r w flags file _bf z cookie close read seek write */ + + /* the usual - (stdin + stdout + stderr) */ +static FILE usual[FOPEN_MAX - 3]; +static struct glue uglue = { 0, FOPEN_MAX - 3, usual }; + +FILE __sF[3] = { + std(__SRD, STDIN_FILENO), /* stdin */ + std(__SWR, STDOUT_FILENO), /* stdout */ + std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ +}; + +struct glue __sglue = { &uglue, 3, __sF }; + +static struct glue * +moreglue(n) + register int n; +{ + register struct glue *g; + register FILE *p; + static FILE empty; + + g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)); + if (g == NULL) + return (NULL); + p = (FILE *)ALIGN(g + 1); + g->next = NULL; + g->niobs = n; + g->iobs = p; + while (--n >= 0) + *p++ = empty; + return (g); +} + +/* + * Find a free FILE for fopen et al. + */ +FILE * +__sfp() +{ + register FILE *fp; + register int n; + register struct glue *g; + + if (!__sdidinit) + __sinit(); + for (g = &__sglue;; g = g->next) { + for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) + if (fp->_flags == 0) + goto found; + if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) + break; + } + return (NULL); +found: + fp->_flags = 1; /* reserve this slot; caller sets real flags */ + fp->_p = NULL; /* no current pointer */ + fp->_w = 0; /* nothing to read or write */ + fp->_r = 0; + fp->_bf._base = NULL; /* no buffer */ + fp->_bf._size = 0; + fp->_lbfsize = 0; /* not line buffered */ + fp->_file = -1; /* no file */ +/* fp->_cookie = ; */ /* caller sets cookie, _read/_write etc */ + fp->_ub._base = NULL; /* no ungetc buffer */ + fp->_ub._size = 0; + fp->_lb._base = NULL; /* no line buffer */ + fp->_lb._size = 0; + return (fp); +} + +/* + * XXX. Force immediate allocation of internal memory. Not used by stdio, + * but documented historically for certain applications. Bad applications. + */ +void +f_prealloc() +{ + register struct glue *g; + int n; + + n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */ + for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) + /* void */; + if (n > 0) + g->next = moreglue(n); +} + +/* + * exit() calls _cleanup() through *__cleanup, set whenever we + * open or buffer a file. This chicanery is done so that programs + * that do not use stdio need not link it all in. + * + * The name `_cleanup' is, alas, fairly well known outside stdio. + */ +void +_cleanup() +{ + /* (void) _fwalk(fclose); */ + (void) _fwalk(__sflush); /* `cheating' */ +} + +/* + * __sinit() is called whenever stdio's internal variables must be set up. + */ +void +__sinit() +{ + /* make sure we clean up on exit */ + __cleanup = _cleanup; /* conservative */ + __sdidinit = 1; +} diff --git a/src/kernel/libroot/posix/stdio/flags.c b/src/kernel/libroot/posix/stdio/flags.c new file mode 100644 index 0000000000..8550daf875 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/flags.c @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +//#include +//#include +#include +#include + +#include + +#include "local.h" + +/* + * Return the (stdio) flags for a given mode. Store the flags + * to be passed to an open() syscall through *optr. + * Return 0 on error. + */ +int +__sflags(mode, optr) + register const char *mode; + int *optr; +{ + register int ret, m, o; + + switch (*mode++) { + + case 'r': /* open for reading */ + ret = __SRD; + m = O_RDONLY; + o = 0; + break; + + case 'w': /* open for writing */ + ret = __SWR; + m = O_WRONLY; + o = O_CREAT | O_TRUNC; + break; + + case 'a': /* open for appending */ + ret = __SWR; + m = O_WRONLY; + o = O_CREAT | O_APPEND; + break; + + default: /* illegal mode */ + errno = EINVAL; + return (0); + } + + /* [rwa]\+ or [rwa]b\+ means read and write */ + if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) { + ret = __SRW; + m = O_RDWR; + } + *optr = m | o; + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/flockfile.c b/src/kernel/libroot/posix/stdio/flockfile.c new file mode 100644 index 0000000000..2bd084c87b --- /dev/null +++ b/src/kernel/libroot/posix/stdio/flockfile.c @@ -0,0 +1,17 @@ +/* $OpenBSD: flockfile.c,v 1.5 2001/09/04 22:17:45 fgsch Exp $ */ + +#include + +/* These are all no-ops until they are implemented */ + +void flockfile(FILE *fp) +{ + return; +} + +void funlockfile(FILE *fp) +{ + return; +} + + diff --git a/src/kernel/libroot/posix/stdio/fopen.c b/src/kernel/libroot/posix/stdio/fopen.c new file mode 100644 index 0000000000..724b4c1ae9 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fopen.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +//#include +#include +#include +#include +#include + +#include "local.h" + +FILE * +fopen(file, mode) + const char *file; + const char *mode; +{ + register FILE *fp; + register int f; + int flags, oflags; + + if ((flags = __sflags(mode, &oflags)) == 0) { + fprintf(stderr, "flags == 0\n"); + return (NULL); + } + if ((fp = __sfp()) == NULL) { + fprintf(stderr, "__sfp == NULL()\n"); + return (NULL); + } + if ((f = open(file, oflags, DEFFILEMODE)) < 0) { + fp->_flags = 0; /* release */ +/* XXX - temporary hack */ + errno = f; + return (NULL); + } + fp->_file = f; + fp->_flags = flags; + fp->_cookie = fp; + fp->_read = __sread; + fp->_write = __swrite; + fp->_seek = __sseek; + fp->_close = __sclose; + + /* + * When opening in append mode, even though we use O_APPEND, + * we need to seek to the end so that ftell() gets the right + * answer. If the user then alters the seek pointer, or + * the file extends, this will fail, but there is not much + * we can do about this. (We could set __SAPP and check in + * fseek and ftell.) + */ + if (oflags & O_APPEND) + (void) __sseek((void *)fp, (fpos_t)0, SEEK_END); + return (fp); +} diff --git a/src/kernel/libroot/posix/stdio/fprintf.c b/src/kernel/libroot/posix/stdio/fprintf.c new file mode 100644 index 0000000000..0e3e21024a --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fprintf.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +int +#ifdef __STDC__ +fprintf(FILE *fp, const char *fmt, ...) +#else +fprintf(fp, fmt, va_alist) + FILE *fp; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = vfprintf(fp, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/fputc.c b/src/kernel/libroot/posix/stdio/fputc.c new file mode 100644 index 0000000000..056550637c --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fputc.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fputc.c,v 1.4 2001/07/09 06:57:44 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "local.h" + +int +fputc(c, fp) + int c; + register FILE *fp; +{ + if (cantwrite(fp)) { + errno = EBADF; + return (EOF); + } + return (putc(c, fp)); +} diff --git a/src/kernel/libroot/posix/stdio/fputs.c b/src/kernel/libroot/posix/stdio/fputs.c new file mode 100644 index 0000000000..a7a1367ebc --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fputs.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fputs.c,v 1.3 1999/08/07 17:35:58 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "fvwrite.h" + +/* + * Write the given string to the given file. + */ +int +fputs(s, fp) + const char *s; + FILE *fp; +{ + struct __suio uio; + struct __siov iov; + + iov.iov_base = (void *)s; + iov.iov_len = uio.uio_resid = strlen(s); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + return (__sfvwrite(fp, &uio)); +} diff --git a/src/kernel/libroot/posix/stdio/fread.c b/src/kernel/libroot/posix/stdio/fread.c new file mode 100644 index 0000000000..08c6f8e13e --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fread.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "local.h" + +size_t +fread(buf, size, count, fp) + void *buf; + size_t size, count; + register FILE *fp; +{ + register size_t resid; + register char *p; + register int r; + size_t total; + + /* + * The ANSI standard requires a return value of 0 for a count + * or a size of 0. Peculiarily, it imposes no such requirements + * on fwrite; it only requires fread to be broken. + */ + if ((resid = count * size) == 0) + return (0); + if (fp->_r < 0) + fp->_r = 0; + total = resid; + p = buf; + while (resid > (r = fp->_r)) { + (void)memcpy((void *)p, (void *)fp->_p, (size_t)r); + fp->_p += r; + /* fp->_r = 0 ... done in __srefill */ + p += r; + resid -= r; + if (__srefill(fp)) { + /* no more input: return partial result */ + return ((total - resid) / size); + } + } + (void)memcpy((void *)p, (void *)fp->_p, resid); + fp->_r -= resid; + fp->_p += resid; + return (count); +} diff --git a/src/kernel/libroot/posix/stdio/fseek.c b/src/kernel/libroot/posix/stdio/fseek.c new file mode 100644 index 0000000000..0dd712b71e --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fseek.c @@ -0,0 +1,261 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include "local.h" + +#define POS_ERR (-(fpos_t)1) + +/* + * Seek the given file to the given offset. + * `Whence' must be one of the three SEEK_* macros. + */ +int +fseeko(fp, offset, whence) + register FILE *fp; + off_t offset; + int whence; +{ + register fpos_t (*seekfn) (void *, fpos_t, int); + fpos_t target, curoff; + size_t n; + struct stat st; + int havepos; + + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + + /* + * Have to be able to seek. + */ + if ((seekfn = fp->_seek) == NULL) { + errno = ESPIPE; /* historic practice */ + return (EOF); + } + + /* + * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. + * After this, whence is either SEEK_SET or SEEK_END. + */ + switch (whence) { + + case SEEK_CUR: + /* + * In order to seek relative to the current stream offset, + * we have to first find the current stream offset a la + * ftell (see ftell for details). + */ + __sflush(fp); /* may adjust seek offset on append stream */ + if (fp->_flags & __SOFF) + curoff = fp->_offset; + else { + curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); + if (curoff == (fpos_t)-1) + return (EOF); + } + if (fp->_flags & __SRD) { + curoff -= fp->_r; + if (HASUB(fp)) + curoff -= fp->_ur; + } else if (fp->_flags & __SWR && fp->_p != NULL) + curoff += fp->_p - fp->_bf._base; + + offset += curoff; + whence = SEEK_SET; + havepos = 1; + break; + + case SEEK_SET: + case SEEK_END: + curoff = 0; /* XXX just to keep gcc quiet */ + havepos = 0; + break; + + default: + errno = EINVAL; + return (EOF); + } + + /* + * Can only optimise if: + * reading (and not reading-and-writing); + * not unbuffered; and + * this is a `regular' Unix file (and hence seekfn==__sseek). + * We must check __NBF first, because it is possible to have __NBF + * and __SOPT both set. + */ + if (fp->_bf._base == NULL) + __smakebuf(fp); + if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) + goto dumb; + if ((fp->_flags & __SOPT) == 0) { + if (seekfn != __sseek || + fp->_file < 0 || fstat(fp->_file, &st) || + S_ISREG(st.st_mode)) { + fp->_flags |= __SNPT; + goto dumb; + } + fp->_blksize = st.st_blksize; + fp->_flags |= __SOPT; + } + + /* + * We are reading; we can try to optimise. + * Figure out where we are going and where we are now. + */ + if (whence == SEEK_SET) + target = offset; + else { + if (fstat(fp->_file, &st)) + goto dumb; + target = st.st_size + offset; + } + + if (!havepos) { + if (fp->_flags & __SOFF) + curoff = fp->_offset; + else { + curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); + if (curoff == POS_ERR) + goto dumb; + } + curoff -= fp->_r; + if (HASUB(fp)) + curoff -= fp->_ur; + } + + /* + * Compute the number of bytes in the input buffer (pretending + * that any ungetc() input has been discarded). Adjust current + * offset backwards by this count so that it represents the + * file offset for the first byte in the current input buffer. + */ + if (HASUB(fp)) { + curoff += fp->_r; /* kill off ungetc */ + n = fp->_up - fp->_bf._base; + curoff -= n; + n += fp->_ur; + } else { + n = fp->_p - fp->_bf._base; + curoff -= n; + n += fp->_r; + } + + /* + * If the target offset is within the current buffer, + * simply adjust the pointers, clear EOF, undo ungetc(), + * and return. (If the buffer was modified, we have to + * skip this; see fgetln.c.) + */ + if ((fp->_flags & __SMOD) == 0 && + target >= curoff && target < curoff + n) { + register int o = target - curoff; + + fp->_p = fp->_bf._base + o; + fp->_r = n - o; + if (HASUB(fp)) + FREEUB(fp); + fp->_flags &= ~__SEOF; + return (0); + } + + /* + * The place we want to get to is not within the current buffer, + * but we can still be kind to the kernel copyout mechanism. + * By aligning the file offset to a block boundary, we can let + * the kernel use the VM hardware to map pages instead of + * copying bytes laboriously. Using a block boundary also + * ensures that we only read one block, rather than two. + */ + curoff = target & ~(fp->_blksize - 1); + if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR) + goto dumb; + fp->_r = 0; + fp->_p = fp->_bf._base; + if (HASUB(fp)) + FREEUB(fp); + fp->_flags &= ~__SEOF; + n = target - curoff; + if (n) { + if (__srefill(fp) || fp->_r < n) + goto dumb; + fp->_p += n; + fp->_r -= n; + } + return (0); + + /* + * We get here if we cannot optimise the seek ... just + * do it. Allow the seek function to change fp->_bf._base. + */ +dumb: + if (__sflush(fp) || + (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) { + return (EOF); + } + /* success: clear EOF indicator and discard ungetc() data */ + if (HASUB(fp)) + FREEUB(fp); + fp->_p = fp->_bf._base; + fp->_r = 0; + /* fp->_w = 0; */ /* unnecessary (I think...) */ + fp->_flags &= ~__SEOF; + return (0); +} + +/* + * fseek()'s offset is a long and sizeof(off_t) != sizeof(long) on all arches + */ +#if defined(__alpha__) && defined(__indr_reference) +__indr_reference(fseeko, fseek); +#else +int +fseek(fp, offset, whence) + register FILE *fp; + long offset; + int whence; +{ + off_t off = offset; + + return(fseeko(fp, off, whence)); +} +#endif diff --git a/src/kernel/libroot/posix/stdio/fvwrite.c b/src/kernel/libroot/posix/stdio/fvwrite.c new file mode 100644 index 0000000000..f86744d6ee --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fvwrite.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "local.h" +#include "fvwrite.h" + +/* + * Write some memory regions. Return zero on success, EOF on error. + * + * This routine is large and unsightly, but most of the ugliness due + * to the three different kinds of output buffering is handled here. + */ +int +__sfvwrite(fp, uio) + register FILE *fp; + register struct __suio *uio; +{ + register size_t len; + register char *p; + register struct __siov *iov; + register int w, s; + char *nl; + int nlknown, nldist; + + if ((len = uio->uio_resid) == 0) { + return (0); + } + /* make sure we can write */ + if (cantwrite(fp)) { + errno = EBADF; + return (EOF); + } + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n)) + + iov = uio->uio_iov; + p = iov->iov_base; + len = iov->iov_len; + iov++; +#define GETIOV(extra_work) \ + while (len == 0) { \ + extra_work; \ + p = iov->iov_base; \ + len = iov->iov_len; \ + iov++; \ + } + if (fp->_flags & __SNBF) { + /* + * Unbuffered: write up to BUFSIZ bytes at a time. + */ + do { + GETIOV(;); + w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ)); + if (w <= 0) + goto err; + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } else if ((fp->_flags & __SLBF) == 0) { + /* + * Fully buffered: fill partially full buffer, if any, + * and then flush. If there is no partial buffer, write + * one _bf._size byte chunk directly (without copying). + * + * String output is a special case: write as many bytes + * as fit, but pretend we wrote everything. This makes + * snprintf() return the number of bytes needed, rather + * than the number used, and avoids its write function + * (so that the write function can be invalid). + */ + do { + GETIOV(;); + if ((fp->_flags & (__SALC | __SSTR)) == + (__SALC | __SSTR) && fp->_w < len) { + size_t blen = fp->_p - fp->_bf._base; + unsigned char *_base; + int _size; + + /* Allocate space exponentially. */ + _size = fp->_bf._size; + do { + _size = (_size << 1) + 1; + } while (_size < blen + len); + _base = realloc(fp->_bf._base, _size + 1); + if (_base == NULL) + goto err; + fp->_w += _size - fp->_bf._size; + fp->_bf._base = _base; + fp->_bf._size = _size; + fp->_p = _base + blen; + } + w = fp->_w; + if (fp->_flags & __SSTR) { + if (len < w) + w = len; + COPY(w); /* copy MIN(fp->_w,len), */ + fp->_w -= w; + fp->_p += w; + w = len; /* but pretend copied all */ + } else if (fp->_p > fp->_bf._base && len > w) { + /* fill and flush */ + COPY(w); + /* fp->_w -= w; */ /* unneeded */ + fp->_p += w; + if (fflush(fp)) + goto err; + } else if (len >= (w = fp->_bf._size)) { + /* write directly */ + w = (*fp->_write)(fp->_cookie, p, w); + if (w <= 0) { + goto err; + } + } else { + /* fill and done */ + w = len; + COPY(w); + fp->_w -= w; + fp->_p += w; + } + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } else { + /* + * Line buffered: like fully buffered, but we + * must check for newlines. Compute the distance + * to the first newline (including the newline), + * or `infinity' if there is none, then pretend + * that the amount to write is MIN(len,nldist). + */ + nlknown = 0; + nldist = 0; /* XXX just to keep gcc happy */ + do { + GETIOV(nlknown = 0); + if (!nlknown) { + nl = memchr((void *)p, '\n', len); + nldist = nl ? nl + 1 - p : len + 1; + nlknown = 1; + } + s = MIN(len, nldist); + w = fp->_w + fp->_bf._size; + if (fp->_p > fp->_bf._base && s > w) { + COPY(w); + /* fp->_w -= w; */ + fp->_p += w; + if (fflush(fp)) + goto err; + } else if (s >= (w = fp->_bf._size)) { + w = (*fp->_write)(fp->_cookie, p, w); + if (w <= 0) + goto err; + } else { + w = s; + COPY(w); + fp->_w -= w; + fp->_p += w; + } + if ((nldist -= w) == 0) { + /* copied the newline: flush and forget */ + if (fflush(fp)) + goto err; + nlknown = 0; + } + p += w; + len -= w; + } while ((uio->uio_resid -= w) != 0); + } + return (0); + +err: + fp->_flags |= __SERR; + return (EOF); +} diff --git a/src/kernel/libroot/posix/stdio/fvwrite.h b/src/kernel/libroot/posix/stdio/fvwrite.h new file mode 100644 index 0000000000..bd7bcde8e9 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fvwrite.h @@ -0,0 +1,56 @@ +/* $OpenBSD: fvwrite.h,v 1.3 1997/07/25 20:30:10 mickey Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * I/O descriptors for __sfvwrite(). + */ +struct __siov { + void *iov_base; + size_t iov_len; +}; +struct __suio { + struct __siov *uio_iov; + int uio_iovcnt; + int uio_resid; +}; + +#if defined(__STDC__) || defined(c_plusplus) +extern int __sfvwrite(FILE *, struct __suio *); +#else +extern int __sfvwrite(); +#endif diff --git a/src/kernel/libroot/posix/stdio/fwalk.c b/src/kernel/libroot/posix/stdio/fwalk.c new file mode 100644 index 0000000000..7d5ec390cf --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fwalk.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: fwalk.c,v 1.3 2001/07/09 06:57:44 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "local.h" +#include "glue.h" + +int +_fwalk(function) + register int (*function)(); +{ + register FILE *fp; + register int n, ret; + register struct glue *g; + + ret = 0; + for (g = &__sglue; g != NULL; g = g->next) + for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) + if (fp->_flags != 0) + ret |= (*function)(fp); + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/fwrite.c b/src/kernel/libroot/posix/stdio/fwrite.c new file mode 100644 index 0000000000..5da5a8e498 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/fwrite.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "local.h" +#include "fvwrite.h" + +/* + * Write `count' objects (each size `size') from memory to the given file. + * Return the number of whole objects written. + */ +size_t +fwrite(buf, size, count, fp) + const void *buf; + size_t size, count; + FILE *fp; +{ + size_t n; + struct __suio uio; + struct __siov iov; + + iov.iov_base = (void *)buf; + uio.uio_resid = iov.iov_len = n = count * size; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + + /* + * The usual case is success (__sfvwrite returns 0); + * skip the divide if this happens, since divides are + * generally slow and since this occurs whenever size==0. + */ + if (__sfvwrite(fp, &uio) == 0) + return (count); + return ((n - uio.uio_resid) / size); +} diff --git a/src/kernel/libroot/posix/stdio/getc.c b/src/kernel/libroot/posix/stdio/getc.c new file mode 100644 index 0000000000..7ad6d39789 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/getc.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: getc.c,v 1.3 1998/11/20 11:18:48 d Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +/* + * A subroutine version of the macro getc_unlocked. + */ +#undef getc_unlocked + +// ToDo: should move in the gnu_stdio.h header (or directly in stdio.h?) +extern int getc_unlocked(FILE *__stream); + +int +getc_unlocked(FILE *fp) +{ + return (__sgetc(fp)); +} + +/* + * A subroutine version of the macro getc. + */ +#undef getc + +int +getc(register FILE *fp) +{ + int c; + + flockfile(fp); + c = __sgetc(fp); + funlockfile(fp); + return (c); +} diff --git a/src/kernel/libroot/posix/stdio/getchar.c b/src/kernel/libroot/posix/stdio/getchar.c new file mode 100644 index 0000000000..42c7626f05 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/getchar.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * A subroutine version of the macro getchar. + */ +#include + +#undef getchar + +int +getchar() +{ + return (getc(stdin)); +} diff --git a/src/kernel/libroot/posix/stdio/gets.c b/src/kernel/libroot/posix/stdio/gets.c new file mode 100644 index 0000000000..152993c38d --- /dev/null +++ b/src/kernel/libroot/posix/stdio/gets.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +//__warn_references(gets, +// "warning: gets() is very unsafe; consider using fgets()"); + +char * +gets(buf) + char *buf; +{ + register int c; + register char *s; + + for (s = buf; (c = getchar()) != '\n';) + if (c == EOF) + if (s == buf) + return (NULL); + else + break; + else + *s++ = c; + *s = 0; + return (buf); +} diff --git a/src/kernel/libroot/posix/stdio/getw.c b/src/kernel/libroot/posix/stdio/getw.c new file mode 100644 index 0000000000..b442c01d69 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/getw.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +int +getw(fp) + FILE *fp; +{ + int x; + + return (fread((void *)&x, sizeof(x), 1, fp) == 1 ? x : EOF); +} diff --git a/src/kernel/libroot/posix/stdio/glue.h b/src/kernel/libroot/posix/stdio/glue.h new file mode 100644 index 0000000000..b68b2403bc --- /dev/null +++ b/src/kernel/libroot/posix/stdio/glue.h @@ -0,0 +1,47 @@ +/* $OpenBSD: glue.h,v 1.2 1996/08/19 08:32:53 tholo Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The first few FILEs are statically allocated; others are dynamically + * allocated and linked in via this glue structure. + */ +struct glue { + struct glue *next; + int niobs; + FILE *iobs; +} __sglue; diff --git a/src/kernel/libroot/posix/stdio/kvsprintf.c b/src/kernel/libroot/posix/stdio/kvsprintf.c new file mode 100644 index 0000000000..999492d675 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/kvsprintf.c @@ -0,0 +1,323 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +/* this file has been superceded by the libc code now in place, but + * for one area, in kernel calls to dprintf/kprintf and sprintf. + */ + +#include +#include +#include +#include +#include + +#if 0 +static unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +static long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} +#endif +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +static unsigned long long do_div(unsigned long long *n, unsigned base) +{ + unsigned long long res; + res = (*n) % (unsigned long long)base; + + *n = (*n) / (unsigned long long)base; + + return res; +} + +static char * number(char * str, long long num, unsigned base, int size, int precision + ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + return str; +} + +/* Forward decl. needed for IP address printing stuff... */ +int sprintf(char * buf, const char *fmt, ...); + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char * str; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str[0]= '0'; + str[1]= 'x'; + str = number(str+2, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } + if (qualifier == 'L') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') { + num = va_arg(args, unsigned long); + if (flags & SIGN) + num = (long) num; + } else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (short) num; + } else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + str = number(str, num, base, field_width, precision, flags); + } + *str = '\0'; + return str-buf; +} + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + diff --git a/src/kernel/libroot/posix/stdio/local.h b/src/kernel/libroot/posix/stdio/local.h new file mode 100644 index 0000000000..cab85e20c0 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/local.h @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Information local to this implementation of stdio, + * in particular, macros and private variables. + */ + +int __sflush (FILE *); +FILE *__sfp (void); +int __srefill (FILE *); +int __sread (void *, char *, int); +int __swrite (void *, char const *, int); +fpos_t __sseek (void *, fpos_t, int); +int __sclose (void *); +void __sinit (void); +void _cleanup (void); +void (*__cleanup) (void); +void __smakebuf (FILE *); +int __swhatbuf (FILE *, size_t *, int *); +int _fwalk (int (*)(FILE *)); +int __swsetup (FILE *); +int __sflags (const char *, int *); + +extern int __sdidinit; + +/* + * Return true if the given FILE cannot be written now. + */ +#define cantwrite(fp) \ + ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ + __swsetup(fp)) + +/* + * Test whether the given stdio file has an active ungetc buffer; + * release such a buffer, without restoring ordinary unread data. + */ +#define HASUB(fp) ((fp)->_ub._base != NULL) +#define FREEUB(fp) { \ + if ((fp)->_ub._base != (fp)->_ubuf) \ + free((char *)(fp)->_ub._base); \ + (fp)->_ub._base = NULL; \ +} + +/* + * test for an fgetln() buffer. + */ +#define HASLB(fp) ((fp)->_lb._base != NULL) +#define FREELB(fp) { \ + free((char *)(fp)->_lb._base); \ + (fp)->_lb._base = NULL; \ +} diff --git a/src/kernel/libroot/posix/stdio/makebuf.c b/src/kernel/libroot/posix/stdio/makebuf.c new file mode 100644 index 0000000000..96ffb4c862 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/makebuf.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include "local.h" + +/* + * Allocate a file buffer, or switch to unbuffered I/O. + * Per the ANSI C standard, ALL tty devices default to line buffered. + * + * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek + * optimisation) right after the fstat() that finds the buffer size. + */ +void +__smakebuf(fp) + register FILE *fp; +{ + register void *p; + register int flags; + size_t size; + int couldbetty; + if (fp->_flags & __SNBF) { + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + flags = __swhatbuf(fp, &size, &couldbetty); + if ((p = malloc(size)) == NULL) { + fp->_flags |= __SNBF; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + __cleanup = _cleanup; + flags |= __SMBF; + fp->_bf._base = fp->_p = p; + fp->_bf._size = size; + /* XXX - once stat is fixed and we have isatty() */ + if (couldbetty && fp->_file < 3) //isatty(fp->_file)) + flags |= __SLBF; + fp->_flags |= flags; +} + +/* + * Internal routine to determine `proper' buffering for a file. + */ +int +__swhatbuf(fp, bufsize, couldbetty) + register FILE *fp; + size_t *bufsize; + int *couldbetty; +{ + struct stat st; + + if (fp->_file < 0 || fstat(fp->_file, &st) < 0) { + *couldbetty = 0; + *bufsize = BUFSIZ; + return (__SNPT); + } + + /* XXX - we don't have stat working yet, so simply do + * this to make sure we don't segfault due to buffer sizes! + */ + st.st_blksize = 0; + + /* could be a tty if it is a character device */ + *couldbetty = S_ISCHR(st.st_mode); + if (st.st_blksize == 0) { + *bufsize = BUFSIZ; + return (__SNPT); + } + + /* + * Optimise fseek() only if it is a regular file. (The test for + * __sseek is mainly paranoia.) It is safe to set _blksize + * unconditionally; it will only be used if __SOPT is also set. + */ + if ((fp->_flags & __SSTR) == 0) { + *bufsize = st.st_blksize; + fp->_blksize = st.st_blksize; + } + return (S_ISREG(st.st_mode) && fp->_seek == __sseek ? + __SOPT : __SNPT); +} diff --git a/src/kernel/libroot/posix/stdio/old_stdio.c b/src/kernel/libroot/posix/stdio/old_stdio.c new file mode 100644 index 0000000000..e44bcca867 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/old_stdio.c @@ -0,0 +1,44 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include +#include + +int __stdio_init(void); /* keep the compiler happy, these two are not supposed */ +int __stdio_deinit(void);/* to be called by anyone except crt0, and crt0 will change soon */ + + +int __stdio_init(void) +{ + return 0; +} + +int __stdio_deinit(void) +{ + return 0; +} + +int printf(const char *fmt, ...) +{ + va_list args; + char buf[1024]; + int i; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); + va_end(args); + + sys_write(1, buf, -1, strlen(buf)); + + return i; +} + +int getchar(void) +{ + char c; + + sys_read(0, &c, 0, 1); + return c; +} diff --git a/src/kernel/libroot/posix/stdio/printf.c b/src/kernel/libroot/posix/stdio/printf.c new file mode 100644 index 0000000000..5dc53d5aee --- /dev/null +++ b/src/kernel/libroot/posix/stdio/printf.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#ifdef __STDC__ +#include +#else +#include +#endif + +int +#ifdef __STDC__ +printf(char const *fmt, ...) +#else +printf(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = vfprintf(stdout, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/putc.c b/src/kernel/libroot/posix/stdio/putc.c new file mode 100644 index 0000000000..18d5a0ab75 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/putc.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "local.h" + +/* + * A subroutine version of the macro putc_unlocked. + */ +#undef putc_unlocked + +int putc_unlocked(int, FILE *); + +int +putc_unlocked(c, fp) + int c; + register FILE *fp; +{ + if (cantwrite(fp)) { + errno = EBADF; + return (EOF); + } + return (__sputc(c, fp)); +} + +/* + * A subroutine version of the macro putc. + */ +#undef putc + +int +putc(c, fp) + int c; + FILE *fp; +{ + int ret; + + flockfile(fp); + ret = putc_unlocked(c, fp); + funlockfile(fp); + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/putchar.c b/src/kernel/libroot/posix/stdio/putchar.c new file mode 100644 index 0000000000..a12a6a4ff1 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/putchar.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#undef putchar + +/* + * A subroutine version of the macro putchar + */ +int +putchar(c) + int c; +{ + register FILE *so = stdout; + + return (__sputc(c, so)); +} diff --git a/src/kernel/libroot/posix/stdio/puts.c b/src/kernel/libroot/posix/stdio/puts.c new file mode 100644 index 0000000000..9256ec7dba --- /dev/null +++ b/src/kernel/libroot/posix/stdio/puts.c @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "fvwrite.h" + +/* + * Write the given string to stdout, appending a newline. + */ +int +puts(s) + char const *s; +{ + size_t c = strlen(s); + struct __suio uio; + struct __siov iov[2]; + + iov[0].iov_base = (void *)s; + iov[0].iov_len = c; + iov[1].iov_base = "\n"; + iov[1].iov_len = 1; + uio.uio_resid = c + 1; + uio.uio_iov = &iov[0]; + uio.uio_iovcnt = 2; + return (__sfvwrite(stdout, &uio) ? EOF : '\n'); +} diff --git a/src/kernel/libroot/posix/stdio/putw.c b/src/kernel/libroot/posix/stdio/putw.c new file mode 100644 index 0000000000..7fa0206244 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/putw.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: putw.c,v 1.3 2001/07/09 06:57:44 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include "fvwrite.h" + +int +putw(w, fp) + int w; + FILE *fp; +{ + struct __suio uio; + struct __siov iov; + + iov.iov_base = &w; + iov.iov_len = uio.uio_resid = sizeof(w); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + return (__sfvwrite(fp, &uio)); +} diff --git a/src/kernel/libroot/posix/stdio/refill.c b/src/kernel/libroot/posix/stdio/refill.c new file mode 100644 index 0000000000..e967ed7e98 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/refill.c @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include "local.h" + +static int +lflush(fp) + FILE *fp; +{ + + if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) + return (__sflush(fp)); + return (0); +} + +/* + * Refill a stdio buffer. + * Return EOF on eof or error, 0 otherwise. + */ +int +__srefill(fp) + register FILE *fp; +{ + + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + + fp->_r = 0; /* largely a convenience for callers */ + + /* SysV does not make this test; take it out for compatibility */ + if (fp->_flags & __SEOF) + return (EOF); + + /* if not already reading, have to be reading and writing */ + if ((fp->_flags & __SRD) == 0) { + if ((fp->_flags & __SRW) == 0) { + errno = EBADF; + fp->_flags |= __SERR; + return (EOF); + } + /* switch to reading */ + if (fp->_flags & __SWR) { + if (__sflush(fp)) + return (EOF); + fp->_flags &= ~__SWR; + fp->_w = 0; + fp->_lbfsize = 0; + } + fp->_flags |= __SRD; + } else { + /* + * We were reading. If there is an ungetc buffer, + * we must have been reading from that. Drop it, + * restoring the previous buffer (if any). If there + * is anything in that buffer, return. + */ + if (HASUB(fp)) { + FREEUB(fp); + if ((fp->_r = fp->_ur) != 0) { + fp->_p = fp->_up; + return (0); + } + } + } + + if (fp->_bf._base == NULL) + __smakebuf(fp); + + /* + * Before reading from a line buffered or unbuffered file, + * flush all line buffered output files, per the ANSI C + * standard. + */ + if (fp->_flags & (__SLBF|__SNBF)) + (void) _fwalk(lflush); + fp->_p = fp->_bf._base; + fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size); + fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ + if (fp->_r <= 0) { + if (fp->_r == 0) + fp->_flags |= __SEOF; + else { + fp->_r = 0; + fp->_flags |= __SERR; + } + return (EOF); + } + return (0); +} diff --git a/src/kernel/libroot/posix/stdio/rewind.c b/src/kernel/libroot/posix/stdio/rewind.c new file mode 100644 index 0000000000..75d28d1bba --- /dev/null +++ b/src/kernel/libroot/posix/stdio/rewind.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: rewind.c,v 1.2 1996/08/19 08:33:02 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +void +rewind(fp) + register FILE *fp; +{ + (void) fseek(fp, 0L, SEEK_SET); + clearerr(fp); + errno = 0; /* not required, but seems reasonable */ +} diff --git a/src/kernel/libroot/posix/stdio/rget.c b/src/kernel/libroot/posix/stdio/rget.c new file mode 100644 index 0000000000..d7737ec19d --- /dev/null +++ b/src/kernel/libroot/posix/stdio/rget.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "local.h" + +/* + * Handle getc() when the buffer ran out: + * Refill, then return the first character + * in the newly-filled buffer. + */ +int +__srget(fp) + register FILE *fp; +{ + if (__srefill(fp) == 0) { + fp->_r--; + return (*fp->_p++); + } + return (EOF); +} diff --git a/src/kernel/libroot/posix/stdio/sprintf.c b/src/kernel/libroot/posix/stdio/sprintf.c new file mode 100644 index 0000000000..5d02ef2b16 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/sprintf.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifdef __STDC__ +# include +#else +# include +#endif +#include "local.h" + + +int +#ifdef __STDC__ +sprintf(char *str, char const *fmt, ...) +#else +sprintf(str, fmt, va_alist) + char *str; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._file = -1; + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = INT_MAX; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = vfprintf(&f, fmt, ap); + va_end(ap); + *f._p = '\0'; + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/sscanf.c b/src/kernel/libroot/posix/stdio/sscanf.c new file mode 100644 index 0000000000..ce0a89dcdb --- /dev/null +++ b/src/kernel/libroot/posix/stdio/sscanf.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#ifdef __STDC__ +#include +#else +#include +#endif +#include "local.h" + +/* ARGSUSED */ +static int +eofread(cookie, buf, len) + void *cookie; + char *buf; + int len; +{ + + return (0); +} + +int +#ifdef __STDC__ +sscanf(const char *str, char const *fmt, ...) +#else +sscanf(str, fmt, va_alist) + const char *str; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._r = strlen(str); + f._read = eofread; + f._ub._base = NULL; + f._lb._base = NULL; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + ret = __svfscanf(&f, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/stdio.c b/src/kernel/libroot/posix/stdio/stdio.c new file mode 100644 index 0000000000..ab4d325a6b --- /dev/null +++ b/src/kernel/libroot/posix/stdio/stdio.c @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "local.h" + +/* + * Small standard I/O/seek/close functions. + * These maintain the `known seek offset' for seek optimisation. + */ +int +__sread(cookie, buf, n) + void *cookie; + char *buf; + int n; +{ + register FILE *fp = cookie; + register int ret; + + ret = read(fp->_file, buf, n); + /* if the read succeeded, update the current offset */ + if (ret >= 0) + fp->_offset += ret; + else + fp->_flags &= ~__SOFF; /* paranoia */ + return (ret); +} + +int +__swrite(cookie, buf, n) + void *cookie; + char const *buf; + int n; +{ + register FILE *fp = cookie; + + if (fp->_flags & __SAPP) + (void) lseek(fp->_file, (off_t)0, SEEK_END); + fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */ + + return (write(fp->_file, buf, n)); +} + +fpos_t +__sseek(cookie, offset, whence) + void *cookie; + fpos_t offset; + int whence; +{ + register FILE *fp = cookie; + register off_t ret; + + ret = lseek(fp->_file, (off_t)offset, whence); + if (ret == (off_t)-1) + fp->_flags &= ~__SOFF; + else { + fp->_flags |= __SOFF; + fp->_offset = ret; + } + return (ret); +} + +int +__sclose(cookie) + void *cookie; +{ + return (close(((FILE *)cookie)->_file)); +} diff --git a/src/kernel/libroot/posix/stdio/ungetc.c b/src/kernel/libroot/posix/stdio/ungetc.c new file mode 100644 index 0000000000..16a4c890ca --- /dev/null +++ b/src/kernel/libroot/posix/stdio/ungetc.c @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "local.h" + +static int __submore (FILE *); +/* + * Expand the ungetc buffer `in place'. That is, adjust fp->_p when + * the buffer moves, so that it points the same distance from the end, + * and move the bytes in the buffer around as necessary so that they + * are all at the end (stack-style). + */ +static int +__submore(fp) + FILE *fp; +{ + register int i; + register unsigned char *p; + + if (fp->_ub._base == fp->_ubuf) { + /* + * Get a new buffer (rather than expanding the old one). + */ + if ((p = malloc((size_t)BUFSIZ)) == NULL) + return (EOF); + fp->_ub._base = p; + fp->_ub._size = BUFSIZ; + p += BUFSIZ - sizeof(fp->_ubuf); + for (i = sizeof(fp->_ubuf); --i >= 0;) + p[i] = fp->_ubuf[i]; + fp->_p = p; + return (0); + } + i = fp->_ub._size; + p = realloc(fp->_ub._base, i << 1); + if (p == NULL) + return (EOF); + /* no overlap (hence can use memcpy) because we doubled the size */ + (void)memcpy((void *)(p + i), (void *)p, (size_t)i); + fp->_p = p + i; + fp->_ub._base = p; + fp->_ub._size = i << 1; + return (0); +} + +int +ungetc(c, fp) + int c; + register FILE *fp; +{ + if (c == EOF) + return (EOF); + if (!__sdidinit) + __sinit(); + if ((fp->_flags & __SRD) == 0) { + /* + * Not already reading: no good unless reading-and-writing. + * Otherwise, flush any current write stuff. + */ + if ((fp->_flags & __SRW) == 0) + return (EOF); + if (fp->_flags & __SWR) { + if (__sflush(fp)) + return (EOF); + fp->_flags &= ~__SWR; + fp->_w = 0; + fp->_lbfsize = 0; + } + fp->_flags |= __SRD; + } + c = (unsigned char)c; + + /* + * If we are in the middle of ungetc'ing, just continue. + * This may require expanding the current ungetc buffer. + */ + if (HASUB(fp)) { + if (fp->_r >= fp->_ub._size && __submore(fp)) + return (EOF); + *--fp->_p = c; + fp->_r++; + return (c); + } + fp->_flags &= ~__SEOF; + + /* + * If we can handle this by simply backing up, do so, + * but never replace the original character. + * (This makes sscanf() work when scanning `const' data.) + */ + if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && + fp->_p[-1] == c) { + fp->_p--; + fp->_r++; + return (c); + } + + /* + * Create an ungetc buffer. + * Initially, we will use the `reserve' buffer. + */ + fp->_ur = fp->_r; + fp->_up = fp->_p; + fp->_ub._base = fp->_ubuf; + fp->_ub._size = sizeof(fp->_ubuf); + fp->_ubuf[sizeof(fp->_ubuf) - 1] = c; + fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1]; + fp->_r = 1; + return (c); +} diff --git a/src/kernel/libroot/posix/stdio/vfprintf.c b/src/kernel/libroot/posix/stdio/vfprintf.c new file mode 100644 index 0000000000..cfc2a34ef2 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/vfprintf.c @@ -0,0 +1,1170 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Actual printf innards. + * + * This code is large and complicated... + */ + +#include + +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#else +#include +#endif + +#include "local.h" +#include "fvwrite.h" + +static void __find_arguments (const char *fmt0, va_list ap, + va_list **argtable); +static int __grow_type_table (unsigned char **typetable, + int *tablesize); + +/* + * Flush out all the vectors defined by the given uio, + * then reset it so that it can be reused. + */ +static int +__sprint(fp, uio) + FILE *fp; + register struct __suio *uio; +{ + register int err; + + if (uio->uio_resid == 0) { + uio->uio_iovcnt = 0; + return (0); + } + err = __sfvwrite(fp, uio); + uio->uio_resid = 0; + uio->uio_iovcnt = 0; + return (err); +} + +/* + * Helper function for `fprintf to unbuffered unix file': creates a + * temporary buffer. We only work on write-only files; this avoids + * worries about ungetc buffers and so forth. + */ +static int +__sbprintf(fp, fmt, ap) + register FILE *fp; + const char *fmt; + va_list ap; +{ + int ret; + FILE fake; + unsigned char buf[BUFSIZ]; + + /* copy the important variables */ + fake._flags = fp->_flags & ~__SNBF; + fake._file = fp->_file; + fake._cookie = fp->_cookie; + fake._write = fp->_write; + + /* set up the buffer */ + fake._bf._base = fake._p = buf; + fake._bf._size = fake._w = sizeof(buf); + fake._lbfsize = 0; /* not actually used, but Just In Case */ + + /* do the work, then copy any error status */ + ret = vfprintf(&fake, fmt, ap); + if (ret >= 0 && fflush(&fake)) + ret = EOF; + if (fake._flags & __SERR) + fp->_flags |= __SERR; + return (ret); +} + + +#ifdef FLOATING_POINT +#include +#include +#include "floatio.h" + +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define DEFPREC 6 + +static char *cvt (double, int, int, char *, int *, int, int *); +static int exponent (char *, int, int); + +#else /* no FLOATING_POINT */ +#define BUF 40 +#endif /* FLOATING_POINT */ + +#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ + + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * Flags used during conversion. + */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGDBL 0x008 /* long double; unimplemented */ +#define LONGINT 0x010 /* long integer */ +#define QUADINT 0x020 /* quad integer */ +#define SHORTINT 0x040 /* short integer */ +#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ +#define FPT 0x100 /* Floating point number */ +int +vfprintf(fp, fmt0, ap) + FILE *fp; + const char *fmt0; + va_list ap; +{ + register char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n, m, n2; /* handy integers (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + register struct __siov *iovp;/* for PRINT macro */ + register int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ + int wc; +#ifdef FLOATING_POINT + char *decimal_point = localeconv()->decimal_point; + char softsign; /* temporary negative sign for floats */ + double _double; /* double precision arguments %[eEfgG] */ + int expt; /* integer value of exponent */ + int expsize; /* character count for expstr */ + int ndig; /* actual number of digits returned by cvt */ + char expstr[7]; /* buffer for exponent string */ +#endif + +#ifdef __GNUC__ /* gcc has builtin quad type (long long) SOS */ +#define quad_t long long +#define u_quad_t unsigned long long +#endif + + u_quad_t _uquad; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int realsz; /* field size expanded by dprec */ + int size; /* size of converted field or string */ + char *xdigs=NULL; /* digits for [xX] conversion */ +#define NIOV 8 + struct __suio uio; /* output information: summary */ + struct __siov iov[NIOV];/* ... and individual io vectors */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + va_list *argtable; /* args, built due to positional arg */ + va_list statargtable[STATIC_ARG_TBL_SIZE]; + int nextarg; /* 1-based argument index */ + va_list orgap; /* original argument pointer */ + + /* + * Choose PADSIZE to trade efficiency vs. size. If larger printf + * fields occur frequently, increase PADSIZE and make the initialisers + * below longer. + */ +#define PADSIZE 16 /* pad chunk size */ + static char blanks[PADSIZE] = + {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + static char zeroes[PADSIZE] = + {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) do { \ + iovp->iov_base = (ptr); \ + iovp->iov_len = (len); \ + uio.uio_resid += (len); \ + iovp++; \ + if (++uio.uio_iovcnt >= NIOV) { \ + if (__sprint(fp, &uio)) \ + goto error; \ + iovp = iov; \ + } \ +} while (0) +#define PAD(howmany, with) do { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT(with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT(with, n); \ + } \ +} while (0) +#define FLUSH() do { \ + if (uio.uio_resid && __sprint(fp, &uio)) \ + goto error; \ + uio.uio_iovcnt = 0; \ + iovp = iov; \ +} while (0) + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#define SARG() \ + (flags&QUADINT ? va_arg(ap, quad_t) : \ + flags&LONGINT ? GETARG(long) : \ + flags&SHORTINT ? (long)(short)GETARG(int) : \ + (long)GETARG(int)) +#define UARG() \ + (flags&QUADINT ? va_arg(ap, u_quad_t) : \ + flags&LONGINT ? GETARG(u_long) : \ + flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ + (u_long)GETARG(u_int)) + + /* + * Get * arguments, including the form *nn$. Preserve the nextarg + * that the argument can be gotten once the type is determined. + */ +#define GETASTER(val) \ + n2 = 0; \ + cp = fmt; \ + while (is_digit(*cp)) { \ + n2 = 10 * n2 + to_digit(*cp); \ + cp++; \ + } \ + if (*cp == '$') { \ + int hold = nextarg; \ + if (argtable == NULL) { \ + argtable = statargtable; \ + __find_arguments(fmt0, orgap, &argtable); \ + } \ + nextarg = n2; \ + val = GETARG(int); \ + nextarg = hold; \ + fmt = ++cp; \ + } \ + else { \ + val = GETARG(int); \ + } + +/* +* Get the argument indexed by nextarg. If the argument table is +* built, use it to get the argument. If its not, get the next +* argument (and arguments must be gotten sequentially). +*/ +#define GETARG(type) \ + (((argtable != NULL) ? (void)(ap = argtable[nextarg]) : (void)0), \ + nextarg++, va_arg(ap, type)) + + /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ + if (cantwrite(fp)) { + errno = EBADF; + return (EOF); + } + + /* optimise fprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && + fp->_file >= 0) + return (__sbprintf(fp, fmt0, ap)); + + fmt = (char *)fmt0; + argtable = NULL; + nextarg = 1; + orgap = ap; + uio.uio_iov = iovp = iov; + uio.uio_resid = 0; + uio.uio_iovcnt = 0; + ret = 0; + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + cp = fmt; + while ((n = mbtowc(&wc, fmt, MB_CUR_MAX)) > 0) { + fmt += n; + if (wc == '%') { + fmt--; + break; + } + } + if ((m = fmt - cp) != 0) { + PRINT(cp, m); + ret += m; + } + if (n <= 0) + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + GETASTER(width); + if (width >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + GETASTER(n); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + if (ch == '$') { + nextarg = n; + if (argtable == NULL) { + argtable = statargtable; + __find_arguments(fmt0, orgap, + &argtable); + } + goto rflag; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + flags |= ZEROPAD; + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + if (ch == '$') { + nextarg = n; + if (argtable == NULL) { + argtable = statargtable; + __find_arguments(fmt0, orgap, + &argtable); + } + goto rflag; + } + width = n; + goto reswitch; +#ifdef FLOATING_POINT + case 'L': + flags |= LONGDBL; + goto rflag; +#endif + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + if (*fmt == 'l') { + fmt++; + flags |= QUADINT; + } else { + flags |= LONGINT; + } + goto rflag; + case 'q': + flags |= QUADINT; + goto rflag; + case 'c': + *(cp = buf) = GETARG(int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + _uquad = SARG(); + if ((quad_t)_uquad < 0) { + _uquad = -_uquad; + sign = '-'; + } + base = DEC; + goto number; +#ifdef FLOATING_POINT + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (prec == -1) { + prec = DEFPREC; + } else if ((ch == 'g' || ch == 'G') && prec == 0) { + prec = 1; + } + + if (flags & LONGDBL) { + _double = (double) GETARG(long double); + } else { + _double = GETARG(double); + } + + /* do this before tricky precision changes */ + if (isinf(_double)) { + if (_double < 0) + sign = '-'; + cp = "Inf"; + size = 3; + break; + } + if (isnan(_double)) { + cp = "NaN"; + size = 3; + break; + } + + flags |= FPT; + cp = cvt(_double, prec, flags, &softsign, + &expt, ch, &ndig); + if (ch == 'g' || ch == 'G') { + if (expt <= -4 || expt > prec) + ch = (ch == 'g') ? 'e' : 'E'; + else + ch = 'g'; + } + if (ch <= 'e') { /* 'e' or 'E' fmt */ + --expt; + expsize = exponent(expstr, expt, ch); + size = expsize + ndig; + if (ndig > 1 || flags & ALT) + ++size; + } else if (ch == 'f') { /* f fmt */ + if (expt > 0) { + size = expt; + if (prec || flags & ALT) + size += prec + 1; + } else /* "0.X" */ + size = prec + 2; + } else if (expt >= ndig) { /* fixed g fmt */ + size = expt; + if (flags & ALT) + ++size; + } else + size = ndig + (expt > 0 ? + 1 : 2 - expt); + + if (softsign) + sign = '-'; + break; +#endif /* FLOATING_POINT */ + case 'n': + if (flags & QUADINT) + *GETARG(quad_t *) = ret; + else if (flags & LONGINT) + *GETARG(long *) = ret; + else if (flags & SHORTINT) + *GETARG(short *) = ret; + else + *GETARG(int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + _uquad = UARG(); + base = OCT; + goto nosign; + case 'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _uquad = (u_long)GETARG(void *); + base = HEX; + xdigs = "0123456789abcdef"; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = GETARG(char *)) == NULL) + cp = "(null)"; + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = strlen(cp); + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + _uquad = UARG(); + base = DEC; + goto nosign; + case 'X': + xdigs = "0123456789ABCDEF"; + goto hex; + case 'x': + xdigs = "0123456789abcdef"; +hex: _uquad = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_uquad != 0 || prec != 0) { + /* + * Unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_uquad >= 10) { + *--cp = to_char(_uquad % 10); + _uquad /= 10; + } + *--cp = to_char(_uquad); + break; + + case HEX: + do { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + cp = "bug in vfprintf: bad base"; + size = strlen(cp); + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, `cp' + * points to a string which (if not flags&LADJUST) should be + * padded out to `width' places. If flags&ZEROPAD, it should + * first be prefixed by any sign or other prefix; otherwise, + * it should be blank padded before the prefix is emitted. + * After any left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print the + * string proper, then emit zeroes required by any leftover + * floating precision; finally, if LADJUST, pad with blanks. + * + * Compute actual size, so we know how much to pad. + * size excludes decimal prec; realsz includes it. + */ + realsz = dprec > size ? dprec : size; + if (sign) + realsz++; + else if (flags & HEXPREFIX) + realsz+= 2; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD(width - realsz, blanks); + + /* prefix */ + if (sign) { + PRINT(&sign, 1); + } else if (flags & HEXPREFIX) { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD(width - realsz, zeroes); + + /* leading zeroes from decimal precision */ + PAD(dprec - size, zeroes); + + /* the string or number proper */ +#ifdef FLOATING_POINT + if ((flags & FPT) == 0) { + PRINT(cp, size); + } else { /* glue together f_p fragments */ + if (ch >= 'f') { /* 'f' or 'g' */ + if (_double == 0) { + /* kludge for __dtoa irregularity */ + PRINT("0", 1); + if (expt < ndig || (flags & ALT) != 0) { + PRINT(decimal_point, 1); + PAD(ndig - 1, zeroes); + } + } else if (expt <= 0) { + PRINT("0", 1); + PRINT(decimal_point, 1); + PAD(-expt, zeroes); + PRINT(cp, ndig); + } else if (expt >= ndig) { + PRINT(cp, ndig); + PAD(expt - ndig, zeroes); + if (flags & ALT) + PRINT(".", 1); + } else { + PRINT(cp, expt); + cp += expt; + PRINT(".", 1); + PRINT(cp, ndig-expt); + } + } else { /* 'e' or 'E' */ + if (ndig > 1 || flags & ALT) { + ox[0] = *cp++; + ox[1] = '.'; + PRINT(ox, 2); + if (_double) { + PRINT(cp, ndig-1); + } else /* 0.[0..] */ + /* __dtoa irregularity */ + PAD(ndig - 1, zeroes); + } else /* XeYYY */ + PRINT(cp, 1); + PRINT(expstr, expsize); + } + } +#else + PRINT(cp, size); +#endif + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD(width - realsz, blanks); + + /* finally, adjust ret */ + ret += width > realsz ? width : realsz; + FLUSH(); /* copy out the I/O vectors */ + } +done: + + FLUSH(); +error: + if (argtable != NULL && argtable != statargtable) + free(argtable); + return (__sferror(fp) ? EOF : ret); + /* NOTREACHED */ +} + +/* + * Type ids for argument type table. + */ +#define T_UNUSED 0 +#define T_SHORT 1 +#define T_U_SHORT 2 +#define TP_SHORT 3 +#define T_INT 4 +#define T_U_INT 5 +#define TP_INT 6 +#define T_LONG 7 +#define T_U_LONG 8 +#define TP_LONG 9 +#define T_QUAD 10 +#define T_U_QUAD 11 +#define TP_QUAD 12 +#define T_DOUBLE 13 +#define T_LONG_DOUBLE 14 +#define TP_CHAR 15 +#define TP_VOID 16 + +/* + * Find all arguments when a positional parameter is encountered. Returns a + * table, indexed by argument number, of pointers to each arguments. The + * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. + * It will be replaces with a malloc-ed on if it overflows. + */ +static void +__find_arguments(fmt0, ap, argtable) + const char *fmt0; + va_list ap; + va_list **argtable; +{ + register char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n, n2; /* handy integer (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + register int flags; /* flags as above */ + unsigned char *typetable; /* table of types */ + unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; + int tablesize; /* current size of type table */ + int tablemax; /* largest used index in table */ + int nextarg; /* 1-based argument index */ + + /* + * Add an argument type to the table, expanding if necessary. + */ +#define ADDTYPE(type) \ + ((nextarg >= tablesize) ? \ + __grow_type_table(&typetable, &tablesize) : 0, \ + typetable[nextarg++] = type, \ + (nextarg > tablemax) ? tablemax = nextarg : 0) + +#define ADDSARG() \ + ((flags&LONGINT) ? ADDTYPE(T_LONG) : \ + ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT))) + +#define ADDUARG() \ + ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \ + ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT))) + + /* + * Add * arguments to the type array. + */ +#define ADDASTER() \ + n2 = 0; \ + cp = fmt; \ + while (is_digit(*cp)) { \ + n2 = 10 * n2 + to_digit(*cp); \ + cp++; \ + } \ + if (*cp == '$') { \ + int hold = nextarg; \ + nextarg = n2; \ + ADDTYPE(T_INT); \ + nextarg = hold; \ + fmt = ++cp; \ + } else { \ + ADDTYPE(T_INT); \ + } + fmt = (char *)fmt0; + typetable = stattypetable; + tablesize = STATIC_ARG_TBL_SIZE; + tablemax = 0; + nextarg = 1; + memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) + /* void */; + if (ch == '\0') + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + case '#': + goto rflag; + case '*': + ADDASTER(); + goto rflag; + case '-': + case '+': + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + ADDASTER(); + goto rflag; + } + while (is_digit(ch)) { + ch = *fmt++; + } + goto reswitch; + case '0': + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + if (ch == '$') { + nextarg = n; + goto rflag; + } + goto reswitch; +#ifdef FLOATING_POINT + case 'L': + flags |= LONGDBL; + goto rflag; +#endif + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + flags |= LONGINT; + goto rflag; + case 'q': + flags |= QUADINT; + goto rflag; + case 'c': + ADDTYPE(T_INT); + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + if (flags & QUADINT) { + ADDTYPE(T_QUAD); + } else { + ADDSARG(); + } + break; +#ifdef FLOATING_POINT + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (flags & LONGDBL) + ADDTYPE(T_LONG_DOUBLE); + else + ADDTYPE(T_DOUBLE); + break; +#endif /* FLOATING_POINT */ + case 'n': + if (flags & QUADINT) + ADDTYPE(TP_QUAD); + else if (flags & LONGINT) + ADDTYPE(TP_LONG); + else if (flags & SHORTINT) + ADDTYPE(TP_SHORT); + else + ADDTYPE(TP_INT); + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + if (flags & QUADINT) + ADDTYPE(T_U_QUAD); + else + ADDUARG(); + break; + case 'p': + ADDTYPE(TP_VOID); + break; + case 's': + ADDTYPE(TP_CHAR); + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + if (flags & QUADINT) + ADDTYPE(T_U_QUAD); + else + ADDUARG(); + break; + case 'X': + case 'x': + if (flags & QUADINT) + ADDTYPE(T_U_QUAD); + else + ADDUARG(); + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + break; + } + } +done: + /* + * Build the argument table. + */ + if (tablemax >= STATIC_ARG_TBL_SIZE) { + *argtable = (va_list *) + malloc(sizeof (va_list) * (tablemax + 1)); + } + +#if 0 + /* XXX is this required? */ + (*argtable) [0] = NULL; +#endif + for (n = 1; n <= tablemax; n++) { + (*argtable)[n] = ap; + switch (typetable[n]) { + case T_UNUSED: + (void) va_arg(ap, int); + break; + case T_SHORT: + (void) va_arg(ap, int); + break; + case T_U_SHORT: + (void) va_arg(ap, int); + break; + case TP_SHORT: + (void) va_arg(ap, short *); + break; + case T_INT: + (void) va_arg(ap, int); + break; + case T_U_INT: + (void) va_arg(ap, unsigned int); + break; + case TP_INT: + (void) va_arg(ap, int *); + break; + case T_LONG: + (void) va_arg(ap, long); + break; + case T_U_LONG: + (void) va_arg(ap, unsigned long); + break; + case TP_LONG: + (void) va_arg(ap, long *); + break; + case T_QUAD: + (void) va_arg(ap, quad_t); + break; + case T_U_QUAD: + (void) va_arg(ap, u_quad_t); + break; + case TP_QUAD: + (void) va_arg(ap, quad_t *); + break; + case T_DOUBLE: + (void) va_arg(ap, double); + break; + case T_LONG_DOUBLE: + (void) va_arg(ap, long double); + break; + case TP_CHAR: + (void) va_arg(ap, char *); + break; + case TP_VOID: + (void) va_arg(ap, void *); + break; + } + } + + if (typetable != NULL && typetable != stattypetable) + free(typetable); +} + +/* + * Increase the size of the type table. + */ +static int +__grow_type_table(typetable, tablesize) + unsigned char **typetable; + int *tablesize; +{ + unsigned char *oldtable = *typetable; + int newsize = *tablesize * 2; + + if (*tablesize == STATIC_ARG_TBL_SIZE) { + *typetable = (unsigned char *) + malloc(sizeof (unsigned char) * newsize); + /* XXX unchecked */ + bcopy(oldtable, *typetable, *tablesize); + } else { + *typetable = (unsigned char *) + realloc(*typetable, sizeof (unsigned char) * newsize); + /* XXX unchecked */ + } + memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize)); + + *tablesize = newsize; + return(0); +} + + +#ifdef FLOATING_POINT + +extern char *__dtoa __P((double, int, int, int *, int *, char **)); + +static char * +cvt(value, ndigits, flags, sign, decpt, ch, length) + double value; + int ndigits, flags, *decpt, ch, *length; + char *sign; +{ + int mode, dsgn; + char *digits, *bp, *rve; + + if (ch == 'f') { + mode = 3; /* ndigits after the decimal point */ + } else { + /* To obtain ndigits after the decimal point for the 'e' + * and 'E' formats, round to ndigits + 1 significant + * figures. + */ + if (ch == 'e' || ch == 'E') { + ndigits++; + } + mode = 2; /* ndigits significant digits */ + } + + if (value < 0) { + value = -value; + *sign = '-'; + } else + *sign = '\000'; + digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); + if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ + bp = digits + ndigits; + if (ch == 'f') { + if (*digits == '0' && value) + *decpt = -ndigits + 1; + bp += *decpt; + } + if (value == 0) /* kludge for __dtoa irregularity */ + rve = bp; + while (rve < bp) + *rve++ = '0'; + } + *length = rve - digits; + return (digits); +} + +static int +exponent(p0, exp, fmtch) + char *p0; + int exp, fmtch; +{ + register char *p, *t; + char expbuf[MAXEXP]; + + p = p0; + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } + else + *p++ = '+'; + t = expbuf + MAXEXP; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXP; *p++ = *t++); + } + else { + *p++ = '0'; + *p++ = to_char(exp); + } + return (p - p0); +} +#endif /* FLOATING_POINT */ diff --git a/src/kernel/libroot/posix/stdio/vfscanf.c b/src/kernel/libroot/posix/stdio/vfscanf.c new file mode 100644 index 0000000000..3f1a8bdc98 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/vfscanf.c @@ -0,0 +1,750 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "local.h" + +#ifdef FLOATING_POINT +#include "floatio.h" +#endif + +#define BUF 513 /* Maximum length of numeric string. */ + +/* + * Flags used during conversion. + */ +#define LONG 0x01 /* l: long or double */ +#define LONGDBL 0x02 /* L: long double; unimplemented */ +#define SHORT 0x04 /* h: short */ +#define QUAD 0x08 /* q: quad */ +#define SUPPRESS 0x10 /* suppress assignment */ +#define POINTER 0x20 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x40 /* do not skip blanks */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ +#define SIGNOK 0x080 /* +/- is (still) legal */ +#define NDIGITS 0x100 /* no digits detected */ + +#define DPTOK 0x200 /* (float) decimal point is still legal */ +#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x200 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x400 /* no zero digits detected */ + +/* + * Conversion types. + */ +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtoq or strtouq */ +#define CT_FLOAT 4 /* floating, i.e., strtod */ + +#define u_char unsigned char +#define u_long unsigned long + +static u_char *__sccl(char *tab, u_char *fmt); + +/* + * vfscanf + */ +int +__svfscanf(fp, fmt0, ap) + register FILE *fp; + char const *fmt0; + va_list ap; +{ + register u_char *fmt = (u_char *)fmt0; + register int c; /* character from format, or conversion */ + register size_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags; /* flags as defined above */ + register char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ + int base; /* base argument to strtoq/strtouq */ + uint64 (*ccfn)(); /* conversion function (strtoq/strtouq) */ + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static short basefix[17] = + { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + + nassigned = 0; + nread = 0; + base = 0; /* XXX just to keep gcc happy */ + ccfn = NULL; /* XXX just to keep gcc happy */ + for (;;) { + c = *fmt++; + if (c == 0) + return (nassigned); + if (isspace(c)) { + while ((fp->_r > 0 || __srefill(fp) == 0) && + isspace(*fp->_p)) + nread++, fp->_r--, fp->_p++; + continue; + } + if (c != '%') + goto literal; + width = 0; + flags = 0; + /* + * switch on the format. continue if done; + * break once format type is derived. + */ +again: c = *fmt++; + switch (c) { + case '%': +literal: + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + if (*fp->_p != c) + goto match_failure; + fp->_r--, fp->_p++; + nread++; + continue; + + case '*': + flags |= SUPPRESS; + goto again; + case 'L': + flags |= LONGDBL; + goto again; + case 'h': + flags |= SHORT; + goto again; + case 'l': + if (*fmt == 'l') { + fmt++; + flags |= QUAD; + } else { + flags |= LONG; + } + goto again; + case 'q': + flags |= QUAD; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + width = width * 10 + c - '0'; + goto again; + + /* + * Conversions. + * Those marked `compat' are for 4.[123]BSD compatibility. + * + * (According to ANSI, E and X formats are supposed + * to the same as e and x. Sorry about that.) + */ + case 'D': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'd': + c = CT_INT; + ccfn = (uint64 (*)())strtoq; + base = 10; + break; + + case 'i': + c = CT_INT; + ccfn = (uint64 (*)())strtoq; + base = 0; + break; + + case 'O': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'o': + c = CT_INT; + ccfn = strtouq; + base = 8; + break; + + case 'u': + c = CT_INT; + ccfn = strtouq; + base = 10; + break; + + case 'X': + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = strtouq; + base = 16; + break; + +#ifdef FLOATING_POINT + case 'E': + case 'G': + case 'e': + case 'f': + case 'g': + c = CT_FLOAT; + break; +#endif + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = __sccl(ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = strtouq; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + *va_arg(ap, short *) = nread; + else if (flags & LONG) + *va_arg(ap, long *) = nread; + else + *va_arg(ap, int *) = nread; + continue; + + /* + * Disgusting backwards compatibility hacks. XXX + */ + case '\0': /* compat */ + return (EOF); + + default: /* compat */ + if (isupper(c)) + flags |= LONG; + c = CT_INT; + ccfn = (uint64 (*)())strtoq; + base = 10; + break; + } + + /* + * We have a conversion that requires input. + */ + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + + /* + * Consume leading white space, except for formats + * that suppress this. + */ + if ((flags & NOSKIP) == 0) { + while (isspace(*fp->_p)) { + nread++; + if (--fp->_r > 0) + fp->_p++; + else if (__srefill(fp)) + goto input_failure; + } + /* + * Note that there is at least one character in + * the buffer, so conversions that do not set NOSKIP + * ca no longer result in an input failure. + */ + } + + /* + * Do the conversion. + */ + switch (c) { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) + width = 1; + if (flags & SUPPRESS) { + size_t sum = 0; + for (;;) { + if ((n = fp->_r) < width) { + sum += n; + width -= n; + fp->_p += n; + if (__srefill(fp)) { + if (sum == 0) + goto input_failure; + break; + } + } else { + sum += width; + fp->_r -= width; + fp->_p += width; + break; + } + } + nread += sum; + } else { + size_t r = fread((void *)va_arg(ap, char *), 1, + width, fp); + + if (r == 0) + goto input_failure; + nread += r; + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = (size_t)~0; /* `infinity' */ + /* take only those things in the class */ + if (flags & SUPPRESS) { + n = 0; + while (ccltab[*fp->_p]) { + n++, fp->_r--, fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) { + if (n == 0) + goto input_failure; + break; + } + } + if (n == 0) + goto match_failure; + } else { + p0 = p = va_arg(ap, char *); + while (ccltab[*fp->_p]) { + fp->_r--; + *p++ = *fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) { + if (p == p0) + goto input_failure; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = (size_t)~0; + if (flags & SUPPRESS) { + n = 0; + while (!isspace(*fp->_p)) { + n++, fp->_r--, fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) + break; + } + nread += n; + } else { + p0 = p = va_arg(ap, char *); + while (!isspace(*fp->_p)) { + fp->_r--; + *p++ = *fp->_p++; + if (--width == 0) + break; + if (fp->_r <= 0 && __srefill(fp)) + break; + } + *p = 0; + nread += p - p0; + nassigned++; + } + continue; + + case CT_INT: + /* scan an integer as if by strtoq/strtouq */ +#ifdef hardway + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; +#else + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof(buf) - 2) + width = sizeof(buf) - 2; + width++; +#endif + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) { + c = *fp->_p; + /* + * Switch on the character; `goto ok' + * if we accept it as a part of number. + */ + switch (c) { + + /* + * The digit 0 is always legal, but is + * special. For %i conversions, if no + * digits (zero or nonzero) have been + * scanned (only signs), we will have + * base==0. In that case, we should set + * it to 8 and enable 0x prefixing. + * Also, if we have not scanned zero digits + * before this, do not turn off prefixing + * (someone else will turn it off if we + * have scanned any nonzero digits). + */ + case '0': + if (base == 0) { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK|NZDIGITS|NDIGITS); + else + flags &= ~(SIGNOK|PFXOK|NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': case 'X': + if (flags & PFXOK && p == buf + 1) { + base = 16; /* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = c; + if (--fp->_r > 0) + fp->_p++; + else if (__srefill(fp)) + break; /* EOF */ + } + /* + * If we had only a sign, it is no good; push + * back the sign. If the number ends in `x', + * it was [sign] '0' 'x', so push back the x + * and treat it as [sign] '0'. + */ + if (flags & NDIGITS) { + if (p > buf) + (void) ungetc(*(u_char *)--p, fp); + goto match_failure; + } + c = ((u_char *)p)[-1]; + if (c == 'x' || c == 'X') { + --p; + (void) ungetc(c, fp); + } + if ((flags & SUPPRESS) == 0) { + uint64 res; + + *p = 0; + res = (*ccfn)(buf, (char **)NULL, base); + if (flags & POINTER) + *va_arg(ap, void **) = + (void *)(long)res; + else if (flags & QUAD) + *va_arg(ap, int64 *) = res; + else if (flags & LONG) + *va_arg(ap, long *) = res; + else if (flags & SHORT) + *va_arg(ap, short *) = res; + else + *va_arg(ap, int *) = res; + nassigned++; + } + nread += p - buf; + break; + +#ifdef FLOATING_POINT + case CT_FLOAT: + /* scan a floating point number as if by strtod */ +#ifdef hardway + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; +#else + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof(buf) - 2) + width = sizeof(buf) - 2; + width++; +#endif + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + for (p = buf; width; width--) { + c = *fp->_p; + /* + * This code mimicks the integer conversion + * code, but is much simpler. + */ + switch (c) { + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + flags &= ~(SIGNOK | NDIGITS); + goto fok; + + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto fok; + } + break; + case '.': + if (flags & DPTOK) { + flags &= ~(SIGNOK | DPTOK); + goto fok; + } + break; + case 'e': case 'E': + /* no exponent without some digits */ + if ((flags&(NDIGITS|EXPOK)) == EXPOK) { + flags = + (flags & ~(EXPOK|DPTOK)) | + SIGNOK | NDIGITS; + goto fok; + } + break; + } + break; + fok: + *p++ = c; + if (--fp->_r > 0) + fp->_p++; + else if (__srefill(fp)) + break; /* EOF */ + } + /* + * If no digits, might be missing exponent digits + * (just give back the exponent) or might be missing + * regular digits, but had sign and/or decimal point. + */ + if (flags & NDIGITS) { + if (flags & EXPOK) { + /* no digits at all */ + while (p > buf) + ungetc(*(u_char *)--p, fp); + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *(u_char *)--p; + if (c != 'e' && c != 'E') { + (void) ungetc(c, fp);/* sign */ + c = *(u_char *)--p; + } + (void) ungetc(c, fp); + } + if ((flags & SUPPRESS) == 0) { + double res; + + *p = 0; + res = strtod(buf, (char **) NULL); + if (flags & LONGDBL) + *va_arg(ap, long double *) = res; + else if (flags & LONG) + *va_arg(ap, double *) = res; + else + *va_arg(ap, float *) = res; + nassigned++; + } + nread += p - buf; + break; +#endif /* FLOATING_POINT */ + } + } +input_failure: + return (nassigned ? nassigned : -1); +match_failure: + return (nassigned); +} + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ +static u_char * +__sccl(tab, fmt) + register char *tab; + register u_char *fmt; +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } else + v = 0; /* default => reject */ + /* should probably use memset here */ + for (n = 0; n < 256; n++) + tab[n] = v; + if (c == 0) + return (fmt - 1);/* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset + * to the opposite of the above. + * + * The first character may be ']' (or '-') without being special; + * the last character may be '-'. + */ + v = 1 - v; + for (;;) { + tab[c] = v; /* take character c */ +doswitch: + n = *fmt++; /* and examine the next */ + switch (n) { + + case 0: /* format ended too soon */ + return (fmt - 1); + + case '-': + /* + * A scanset of the form + * [01+-] + * is defined as `the digit 0, the digit 1, + * the character +, the character -', but + * the effect of a scanset such as + * [a-zA-Z0-9] + * is implementation defined. The V7 Unix + * scanf treats `a-z' as `the letters a through + * z', but treats `a-a' as `the letter a, the + * character -, and the letter a'. + * + * For compatibility, the `-' is not considerd + * to define a range if the character following + * it is either a close bracket (required by ANSI) + * or is not numerically greater than the character + * we just stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do { /* fill in the range */ + tab[++c] = v; + } while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + /* + * Alas, the V7 Unix scanf also treats formats + * such as [a-c-e] as `the letters a through e'. + * This too is permitted by the standard.... + */ + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return (fmt - 1); + if (c == ']') + return (fmt); +#endif + break; + + case ']': /* end of scanset */ + return (fmt); + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} diff --git a/src/kernel/libroot/posix/stdio/vscanf.c b/src/kernel/libroot/posix/stdio/vscanf.c new file mode 100644 index 0000000000..4f87463780 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/vscanf.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Donn Seeley at UUNET Technologies, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +int +vscanf(fmt, ap) + const char *fmt; + va_list ap; +{ + + return (__svfscanf(stdin, fmt, ap)); +} diff --git a/src/kernel/libroot/posix/stdio/vsprintf.c b/src/kernel/libroot/posix/stdio/vsprintf.c new file mode 100644 index 0000000000..cc95b6a046 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/vsprintf.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + + +int +vsprintf(char *str, const char *fmt, va_list ap) +{ + int ret; + FILE f; + + f._file = -1; + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = INT_MAX; + ret = vfprintf(&f, fmt, ap); + *f._p = '\0'; + return (ret); +} diff --git a/src/kernel/libroot/posix/stdio/wbuf.c b/src/kernel/libroot/posix/stdio/wbuf.c new file mode 100644 index 0000000000..1ad5bb633b --- /dev/null +++ b/src/kernel/libroot/posix/stdio/wbuf.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "local.h" + +/* + * Write the given character into the (probably full) buffer for + * the given file. Flush the buffer out if it is or becomes full, + * or if c=='\n' and the file is line buffered. + */ +int +__swbuf(c, fp) + register int c; + register FILE *fp; +{ + register int n; + + /* + * In case we cannot write, or longjmp takes us out early, + * make sure _w is 0 (if fully- or un-buffered) or -_bf._size + * (if line buffered) so that we will get called again. + * If we did not do this, a sufficient number of putc() + * calls might wrap _w from negative to positive. + */ + fp->_w = fp->_lbfsize; + if (cantwrite(fp)) { + errno = EBADF; + return (EOF); + } + c = (unsigned char)c; + + /* + * If it is completely full, flush it out. Then, in any case, + * stuff c into the buffer. If this causes the buffer to fill + * completely, or if c is '\n' and the file is line buffered, + * flush it (perhaps a second time). The second flush will always + * happen on unbuffered streams, where _bf._size==1; fflush() + * guarantees that putc() will always call wbuf() by setting _w + * to 0, so we need not do anything else. + */ + n = fp->_p - fp->_bf._base; + if (n >= fp->_bf._size) { + if (fflush(fp)) + return (EOF); + n = 0; + } + fp->_w--; + *fp->_p++ = c; + if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n')) + if (fflush(fp)) + return (EOF); + return (c); +} diff --git a/src/kernel/libroot/posix/stdio/wsetup.c b/src/kernel/libroot/posix/stdio/wsetup.c new file mode 100644 index 0000000000..c9a92a15a2 --- /dev/null +++ b/src/kernel/libroot/posix/stdio/wsetup.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "local.h" + +/* + * Various output routines call wsetup to be sure it is safe to write, + * because either _flags does not include __SWR, or _buf is NULL. + * _wsetup returns 0 if OK to write, nonzero otherwise. + */ +int +__swsetup(fp) + register FILE *fp; +{ + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + + /* + * If we are not writing, we had better be reading and writing. + */ + if ((fp->_flags & __SWR) == 0) { + if ((fp->_flags & __SRW) == 0) + return (EOF); + if (fp->_flags & __SRD) { + /* clobber any ungetc data */ + if (HASUB(fp)) + FREEUB(fp); + fp->_flags &= ~(__SRD|__SEOF); + fp->_r = 0; + fp->_p = fp->_bf._base; + } + fp->_flags |= __SWR; + } + + /* + * Make a buffer if necessary, then set _w. + */ + if (fp->_bf._base == NULL) + __smakebuf(fp); + if (fp->_flags & __SLBF) { + /* + * It is line buffered, so make _lbfsize be -_bufsize + * for the putc() macro. We will change _lbfsize back + * to 0 whenever we turn off __SWR. + */ + fp->_w = 0; + fp->_lbfsize = -fp->_bf._size; + } else + fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size; + return (0); +} diff --git a/src/kernel/libroot/posix/stdlib/Jamfile b/src/kernel/libroot/posix/stdlib/Jamfile new file mode 100644 index 0000000000..82721fe7ef --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/Jamfile @@ -0,0 +1,20 @@ +SubDir OBOS_TOP src kernel libroot posix stdlib ; + +KernelObjects + <$(SOURCE_GRIST)>assert.c + <$(SOURCE_GRIST)>atoi.c + <$(SOURCE_GRIST)>bsearch.c + <$(SOURCE_GRIST)>env.c + <$(SOURCE_GRIST)>heapsort.c + <$(SOURCE_GRIST)>merge.c + <$(SOURCE_GRIST)>multibyte.c + <$(SOURCE_GRIST)>qsort.c + <$(SOURCE_GRIST)>radixsort.c + <$(SOURCE_GRIST)>rand.c + <$(SOURCE_GRIST)>random.c + <$(SOURCE_GRIST)>realpath.c + <$(SOURCE_GRIST)>strtoq.c + <$(SOURCE_GRIST)>strtouq.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/stdlib/assert.c b/src/kernel/libroot/posix/stdlib/assert.c new file mode 100644 index 0000000000..76cfb4a5de --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/assert.c @@ -0,0 +1,15 @@ +/* +** Copyright 2002, Travis Geiselbrecht. All rights reserved. +** Copyright 2002, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include + +void +_assert(char const *s1, int l, char const *s2) +{ + (void)(s1); + (void)(l); + (void)(s2); +} diff --git a/src/kernel/libroot/posix/stdlib/atoi.c b/src/kernel/libroot/posix/stdlib/atoi.c new file mode 100644 index 0000000000..038c4c08fc --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/atoi.c @@ -0,0 +1,86 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include + +static int hexval(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return 0; +} + +int atoi(const char *num) +{ + int value = 0; + if (num[0] == '0' && num[1] == 'x') { + // hex + num += 2; + while (*num && isxdigit(*num)) + value = value * 16 + hexval(*num++); + } else { + // decimal + while (*num && isdigit(*num)) + value = value * 10 + *num++ - '0'; + } + + return value; +} + +unsigned int atoui(const char *num) +{ + int value = 0; + if (num[0] == '0' && num[1] == 'x') { + // hex + num += 2; + while (*num && isxdigit(*num)) + value = value * 16 + hexval(*num++); + } else { + // decimal + while (*num && isdigit(*num)) + value = value * 10 + *num++ - '0'; + } + + return value; +} + +long atol(const char *num) +{ + int value = 0; + if (num[0] == '0' && num[1] == 'x') { + // hex + num += 2; + while (*num && isxdigit(*num)) + value = value * 16 + hexval(*num++); + } else { + // decimal + while (*num && isdigit(*num)) + value = value * 10 + *num++ - '0'; + } + + return value; +} + +unsigned long atoul(const char *num) +{ + int value = 0; + if (num[0] == '0' && num[1] == 'x') { + // hex + num += 2; + while (*num && isxdigit(*num)) + value = value * 16 + hexval(*num++); + } else { + // decimal + while (*num && isdigit(*num)) + value = value * 10 + *num++ - '0'; + } + + return value; +} diff --git a/src/kernel/libroot/posix/stdlib/bsearch.c b/src/kernel/libroot/posix/stdlib/bsearch.c new file mode 100644 index 0000000000..9c51bd1f26 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/bsearch.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +//#include +#include + +/* + * Perform a binary search. + * + * The code below is a bit sneaky. After a comparison fails, we + * divide the work in half by moving either left or right. If lim + * is odd, moving left simply involves halving lim: e.g., when lim + * is 5 we look at item 2, so we change lim to 2 so that we will + * look at items 0 & 1. If lim is even, the same applies. If lim + * is odd, moving right again involes halving lim, this time moving + * the base up one item past p: e.g., when lim is 5 we change base + * to item 3 and make lim 2 so that we will look at items 3 and 4. + * If lim is even, however, we have to shrink it by one before + * halving: e.g., when lim is 4, we still looked at item 2, so we + * have to make lim 3, then halve, obtaining 1, so that we will only + * look at item 3. + */ +void * +bsearch( + void const *key, + void const *base0, + size_t nmemb, + size_t size, + int (*compar)(void const *, void const *) +) +{ + char const *base = base0; + size_t lim; + int cmp; + void const *p; + + for (lim = nmemb; lim != 0; lim >>= 1) { + p = base + (lim >> 1) * size; + cmp = (*compar)(key, p); + if (cmp == 0) { + return (void *)p; + } + if (cmp > 0) { /* key > p: move right */ + base = (char *)p + size; + lim--; + } /* else move left */ + } + + return NULL; +} diff --git a/src/kernel/libroot/posix/stdlib/env.c b/src/kernel/libroot/posix/stdlib/env.c new file mode 100644 index 0000000000..d0b2de2564 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/env.c @@ -0,0 +1,24 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include + + +int setenv(const char *name, const char *value, int overwrite) +{ + return sys_setenv(name, value, overwrite); +} + + +char *getenv(const char *name) +{ + char *value; + int rc; + + rc = sys_getenv(name, &value); + if (rc < 0) + return NULL; + return value; +} diff --git a/src/kernel/libroot/posix/stdlib/heapsort.c b/src/kernel/libroot/posix/stdlib/heapsort.c new file mode 100644 index 0000000000..02c7878e88 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/heapsort.c @@ -0,0 +1,189 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)heapsort.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +/* + * Swap two areas of size number of bytes. Although qsort(3) permits random + * blocks of memory to be sorted, sorting pointers is almost certainly the + * common case (and, were it not, could easily be made so). Regardless, it + * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer + * arithmetic gets lost in the time required for comparison function calls. + */ +#define SWAP(a, b, count, size, tmp) { \ + count = size; \ + do { \ + tmp = *a; \ + *a++ = *b; \ + *b++ = tmp; \ + } while (--count); \ +} + +/* Copy one block of size size to another. */ +#define COPY(a, b, count, size, tmp1, tmp2) { \ + count = size; \ + tmp1 = a; \ + tmp2 = b; \ + do { \ + *tmp1++ = *tmp2++; \ + } while (--count); \ +} + +/* + * Build the list into a heap, where a heap is defined such that for + * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N. + * + * There two cases. If j == nmemb, select largest of Ki and Kj. If + * j < nmemb, select largest of Ki, Kj and Kj+1. + */ +#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \ + for (par_i = initval; (child_i = par_i * 2) <= nmemb; \ + par_i = child_i) { \ + child = base + child_i * size; \ + if (child_i < nmemb && compar(child, child + size) < 0) { \ + child += size; \ + ++child_i; \ + } \ + par = base + par_i * size; \ + if (compar(child, par) <= 0) \ + break; \ + SWAP(par, child, count, size, tmp); \ + } \ +} + +/* + * Select the top of the heap and 'heapify'. Since by far the most expensive + * action is the call to the compar function, a considerable optimization + * in the average case can be achieved due to the fact that k, the displaced + * elememt, is ususally quite small, so it would be preferable to first + * heapify, always maintaining the invariant that the larger child is copied + * over its parent's record. + * + * Then, starting from the *bottom* of the heap, finding k's correct place, + * again maintianing the invariant. As a result of the invariant no element + * is 'lost' when k is assigned its correct place in the heap. + * + * The time savings from this optimization are on the order of 15-20% for the + * average case. See Knuth, Vol. 3, page 158, problem 18. + * + * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset. + */ +#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \ + for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \ + child = base + child_i * size; \ + if (child_i < nmemb && compar(child, child + size) < 0) { \ + child += size; \ + ++child_i; \ + } \ + par = base + par_i * size; \ + COPY(par, child, count, size, tmp1, tmp2); \ + } \ + for (;;) { \ + child_i = par_i; \ + par_i = child_i / 2; \ + child = base + child_i * size; \ + par = base + par_i * size; \ + if (child_i == 1 || compar(k, par) < 0) { \ + COPY(child, k, count, size, tmp1, tmp2); \ + break; \ + } \ + COPY(child, par, count, size, tmp1, tmp2); \ + } \ +} + +/* + * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average + * and worst. While heapsort is faster than the worst case of quicksort, + * the BSD quicksort does median selection so that the chance of finding + * a data set that will trigger the worst case is nonexistent. Heapsort's + * only advantage over quicksort is that it requires little additional memory. + */ +int +heapsort(void *vbase, size_t nmemb, size_t size, int (*compar)(void const *, void const *)) +{ + size_t cnt; + size_t i; + size_t j; + size_t l; + char tmp; + char *tmp1; + char *tmp2; + char *base; + char *k; + char *p; + char *t; + + if (nmemb <= 1) { + return (0); + } + + if (!size) { +// errno = EINVAL; + return (-1); + } + + if ((k = malloc(size)) == NULL) { + return (-1); + } + + /* + * Items are numbered from 1 to nmemb, so offset from size bytes + * below the starting address. + */ + base = (char *)vbase - size; + + for (l = nmemb / 2 + 1; --l;) + CREATE(l, nmemb, i, j, t, p, size, cnt, tmp); + + /* + * For each element of the heap, save the largest element into its + * final slot, save the displaced element (k), then recreate the + * heap. + */ + while (nmemb > 1) { + COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2); + COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2); + --nmemb; + SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2); + } + free(k); + return (0); +} diff --git a/src/kernel/libroot/posix/stdlib/merge.c b/src/kernel/libroot/posix/stdlib/merge.c new file mode 100644 index 0000000000..17add08968 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/merge.c @@ -0,0 +1,361 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Peter McIlroy. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Hybrid exponential search/linear search merge sort with hybrid + * natural/pairwise first pass. Requires about .3% more comparisons + * for random data than LSMS with pairwise first pass alone. + * It works for objects as small as two bytes. + */ + +#define NATURAL +#define THRESHOLD 16 /* Best choice for natural merge cut-off. */ + +/* #define NATURAL to get hybrid natural merge. + * (The default is pairwise merging.) + */ + +#include + +#include +#include +#include + +static void setup(u_char *, u_char *, size_t, size_t, int (*)()); +static void insertionsort(u_char *, size_t, size_t, int (*)()); + +#define ISIZE sizeof(int) +#define PSIZE sizeof(u_char *) +#define ICOPY_LIST(src, dst, last) \ + do \ + *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \ + while(src < last) +#define ICOPY_ELT(src, dst, i) \ + do \ + *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \ + while (i -= ISIZE) + +#define CCOPY_LIST(src, dst, last) \ + do \ + *dst++ = *src++; \ + while (src < last) +#define CCOPY_ELT(src, dst, i) \ + do \ + *dst++ = *src++; \ + while (i -= 1) + +/* + * Find the next possible pointer head. (Trickery for forcing an array + * to do double duty as a linked list when objects do not align with word + * boundaries. + */ +/* Assumption: PSIZE is a power of 2. */ +#define EVAL(p) (u_char **) \ + ((u_char *)0 + \ + (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1))) + +/* + * Arguments are as for qsort. + */ +int +mergesort(void *base, size_t nmemb, size_t size, int (*cmp)(void const *, void const *)) +{ + size_t i; + int sense; + int big, iflag; + u_char *f1; + u_char *f2; + u_char *t; + u_char *b; + u_char *tp2; + u_char *q; + u_char *l1; + u_char *l2; + u_char *list2; + u_char *list1; + u_char *p2; + u_char *p; + u_char *last; + u_char **p1; + + if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */ +// errno = EINVAL; + return (-1); + } + + if (nmemb == 0) { + return (0); + } + + /* + * XXX + * Stupid subtraction for the Cray. + */ + iflag = 0; + if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE)) + iflag = 1; + + if ((list2 = malloc(nmemb * size + PSIZE)) == NULL) + return (-1); + + list1 = base; + setup(list1, list2, nmemb, size, cmp); + last = list2 + nmemb * size; + i = big = 0; + while (*EVAL(list2) != last) { + l2 = list1; + p1 = EVAL(list1); + for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) { + p2 = *EVAL(p2); + f1 = l2; + f2 = l1 = list1 + (p2 - list2); + if (p2 != last) + p2 = *EVAL(p2); + l2 = list1 + (p2 - list2); + while (f1 < l1 && f2 < l2) { + if ((*cmp)(f1, f2) <= 0) { + q = f2; + b = f1, t = l1; + sense = -1; + } else { + q = f1; + b = f2, t = l2; + sense = 0; + } + if (!big) { /* here i = 0 */ + while ((b += size) < t && cmp(q, b) >sense) + if (++i == 6) { + big = 1; + goto EXPONENTIAL; + } + } else { +EXPONENTIAL: for (i = size; ; i <<= 1) + if ((p = (b + i)) >= t) { + if ((p = t - size) > b && + (*cmp)(q, p) <= sense) + t = p; + else + b = p; + break; + } else if ((*cmp)(q, p) <= sense) { + t = p; + if (i == size) + big = 0; + goto FASTCASE; + } else + b = p; + while (t > b+size) { + i = (((t - b) / size) >> 1) * size; + if ((*cmp)(q, p = b + i) <= sense) + t = p; + else + b = p; + } + goto COPY; +FASTCASE: while (i > size) + if ((*cmp)(q, + p = b + (i >>= 1)) <= sense) + t = p; + else + b = p; +COPY: b = t; + } + i = size; + if (q == f1) { + if (iflag) { + ICOPY_LIST(f2, tp2, b); + ICOPY_ELT(f1, tp2, i); + } else { + CCOPY_LIST(f2, tp2, b); + CCOPY_ELT(f1, tp2, i); + } + } else { + if (iflag) { + ICOPY_LIST(f1, tp2, b); + ICOPY_ELT(f2, tp2, i); + } else { + CCOPY_LIST(f1, tp2, b); + CCOPY_ELT(f2, tp2, i); + } + } + } + if (f2 < l2) { + if (iflag) + ICOPY_LIST(f2, tp2, l2); + else + CCOPY_LIST(f2, tp2, l2); + } else if (f1 < l1) { + if (iflag) + ICOPY_LIST(f1, tp2, l1); + else + CCOPY_LIST(f1, tp2, l1); + } + *p1 = l2; + } + tp2 = list1; /* swap list1, list2 */ + list1 = list2; + list2 = tp2; + last = list2 + nmemb*size; + } + if (base == list2) { + memmove(list2, list1, nmemb*size); + list2 = list1; + } + free(list2); + return (0); +} + +#define swap(a, b) { \ + s = b; \ + i = size; \ + do { \ + tmp = *a; *a++ = *s; *s++ = tmp; \ + } while (--i); \ + a -= size; \ + } +#define reverse(bot, top) { \ + s = top; \ + do { \ + i = size; \ + do { \ + tmp = *bot; *bot++ = *s; *s++ = tmp; \ + } while (--i); \ + s -= size2; \ + } while(bot < s); \ +} + +/* + * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of + * increasing order, list2 in a corresponding linked list. Checks for runs + * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL + * is defined. Otherwise simple pairwise merging is used.) + */ +static +void +setup(u_char *list1, u_char *list2, size_t n, size_t size, int (*cmp)(void const *, void const *)) +{ + int i, length, size2, tmp, sense; + u_char *f1, *f2, *s, *l2, *last, *p2; + + size2 = size*2; + if (n <= 5) { + insertionsort(list1, n, size, cmp); + *EVAL(list2) = (u_char*) list2 + n*size; + return; + } + /* + * Avoid running pointers out of bounds; limit n to evens + * for simplicity. + */ + i = 4 + (n & 1); + insertionsort(list1 + (n - i) * size, i, size, cmp); + last = list1 + size * (n - i); + *EVAL(list2 + (last - list1)) = list2 + n * size; + +#ifdef NATURAL + p2 = list2; + f1 = list1; + sense = (cmp(f1, f1 + size) > 0); + for (; f1 < last; sense = !sense) { + length = 2; + /* Find pairs with same sense. */ + for (f2 = f1 + size2; f2 < last; f2 += size2) { + if ((cmp(f2, f2+ size) > 0) != sense) + break; + length += 2; + } + if (length < THRESHOLD) { /* Pairwise merge */ + do { + p2 = *EVAL(p2) = f1 + size2 - list1 + list2; + if (sense > 0) + swap (f1, f1 + size); + } while ((f1 += size2) < f2); + } else { /* Natural merge */ + l2 = f2; + for (f2 = f1 + size2; f2 < l2; f2 += size2) { + if ((cmp(f2-size, f2) > 0) != sense) { + p2 = *EVAL(p2) = f2 - list1 + list2; + if (sense > 0) + reverse(f1, f2-size); + f1 = f2; + } + } + if (sense > 0) + reverse (f1, f2-size); + f1 = f2; + if (f2 < last || cmp(f2 - size, f2) > 0) + p2 = *EVAL(p2) = f2 - list1 + list2; + else + p2 = *EVAL(p2) = list2 + n*size; + } + } +#else /* pairwise merge only. */ + for (f1 = list1, p2 = list2; f1 < last; f1 += size2) { + p2 = *EVAL(p2) = p2 + size2; + if (cmp (f1, f1 + size) > 0) + swap(f1, f1 + size); + } +#endif /* NATURAL */ +} + +/* + * This is to avoid out-of-bounds addresses in sorting the + * last 4 elements. + */ +static +void +insertionsort(u_char *a, size_t n,size_t size, int (*cmp)(const void *, const void *)) +{ + u_char *ai; + u_char *s; + u_char *t; + u_char *u; + u_char tmp; + int i; + + for (ai = a+size; --n >= 1; ai += size) { + for (t = ai; t > a; t -= size) { + u = t - size; + if (cmp(u, t) <= 0) + break; + swap(u, t); + } + } +} diff --git a/src/kernel/libroot/posix/stdlib/multibyte.c b/src/kernel/libroot/posix/stdlib/multibyte.c new file mode 100644 index 0000000000..6f75d14b41 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/multibyte.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * Stub multibyte character functions. + * This cheezy implementation is fixed to the native single-byte + * character set. + */ + +int +mblen(s, n) + const char *s; + size_t n; +{ + if (s == NULL || *s == '\0') + return 0; + if (n == 0) + return -1; + return 1; +} + +/*ARGSUSED*/ +int +mbtowc(pwc, s, n) + int *pwc; + const char *s; + size_t n; +{ + if (s == NULL) + return 0; + if (n == 0) + return -1; + if (pwc) + *pwc = (int) *s; + return (*s != '\0'); +} + +/*ARGSUSED*/ +int +wctomb(char *s, int wchar) +{ + if (s == NULL) + return 0; + + *s = (char) wchar; + return 1; +} + +/*ARGSUSED*/ +size_t +mbstowcs(pwcs, s, n) + int *pwcs; + const char *s; + size_t n; +{ + int count = 0; + + if (n != 0) { + do { + if ((*pwcs++ = (int) *s++) == 0) + break; + count++; + } while (--n != 0); + } + + return count; +} + +/*ARGSUSED*/ +size_t +wcstombs(s, pwcs, n) + char *s; + const int *pwcs; + size_t n; +{ + int count = 0; + + if (n != 0) { + do { + if ((*s++ = (char) *pwcs++) == 0) + break; + count++; + } while (--n != 0); + } + + return count; +} + diff --git a/src/kernel/libroot/posix/stdlib/qsort.c b/src/kernel/libroot/posix/stdlib/qsort.c new file mode 100644 index 0000000000..98b30e8ec1 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/qsort.c @@ -0,0 +1,181 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; +#endif +static const char rcsid[] = + "$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.8 1999/08/28 00:01:35 peter Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +typedef int cmp_t(void const *, void const *); +static inline char *med3(char *, char *, char *, cmp_t *); +static inline void swapfunc(char *, char *, int, int); + + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *) (parmi); \ + register TYPE *pj = (TYPE *) (parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline +void +swapfunc(char *a, char *b, int n, int swaptype) +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +static inline +char * +med3(char *a, char *b, char *c, cmp_t *cmp) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} + +void +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +{ + char *pa; + char *pb; + char *pc; + char *pd; + char *pl; + char *pm; + char *pn; + int d; + int r; + int swaptype; + int swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (r = cmp(pb, a)) <= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min((int)(pd - pc), (int)(pn - pd - es)); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > (int)es) + qsort(a, r / es, es, cmp); + if ((r = pd - pc) > (int)es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} diff --git a/src/kernel/libroot/posix/stdlib/radixsort.c b/src/kernel/libroot/posix/stdlib/radixsort.c new file mode 100644 index 0000000000..706fddcec9 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/radixsort.c @@ -0,0 +1,318 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Peter McIlroy and by Dan Bernstein at New York University, + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Radixsort routines. + * + * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack. + * Use radixsort(a, n, trace, endchar) for this case. + * + * For stable sorting (using N extra pointers) use sradixsort(), which calls + * r_sort_b(). + * + * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic, + * "Engineering Radix Sort". + */ + +#include +#include +#include + +typedef struct { + const u_char **sa; + int sn, si; +} stack; + +static inline void simplesort(u_char const **, int, int, u_char const *, u_int); +static void r_sort_a(u_char const **, int, int, u_char const *, u_int); +static void r_sort_b(u_char const **, u_char const **, int, int, u_char const *, u_int); + +#define THRESHOLD 20 /* Divert to simplesort(). */ +#define SIZE 512 /* Default stack size. */ + +#define SETUP { \ + if (tab == NULL) { \ + tr = tr0; \ + for (c = 0; c < endch; c++) \ + tr0[c] = c + 1; \ + tr0[c] = 0; \ + for (c++; c < 256; c++) \ + tr0[c] = c; \ + endch = 0; \ + } else { \ + endch = tab[endch]; \ + tr = tab; \ + if (endch != 0 && endch != 255) { \ + /* errno = EINVAL; */ \ + return (-1); \ + } \ + } \ +} + +int +radixsort(u_char const **a, int n, u_char const *tab, u_int endch) +{ + u_char const *tr; + u_int c; + u_char tr0[256]; + + SETUP; + r_sort_a(a, n, 0, tr, endch); + return (0); +} + +int +sradixsort(u_char const **a, int n, u_char const *tab, u_int endch) +{ + u_char const *tr; + u_char const **ta; + u_int c; + u_char tr0[256]; + + SETUP; + if (n < THRESHOLD) + simplesort(a, n, 0, tr, endch); + else { + if ((ta = malloc(n * sizeof(a))) == NULL) + return (-1); + r_sort_b(a, ta, n, 0, tr, endch); + free(ta); + } + return (0); +} + +#define empty(s) (s >= sp) +#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si +#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i +#define swap(a, b, t) t = a, a = b, b = t + +/* Unstable, in-place sort. */ +static void +r_sort_a(u_char const **a, int n, int i, u_char const *tr, u_int endch) +{ + static u_int count[256]; + static int nc; + static u_int bmin; + u_int c; + u_char const **ak; + u_char const *r; + stack s[SIZE]; + stack *sp; + stack *sp0; + stack *sp1; + stack temp; + u_int *cp; + u_int bigc; + u_char const **an; + u_char const *t; + u_char const **aj; + u_char const **top[256]; + + /* Set up stack. */ + sp = s; + push(a, n, i); + while (!empty(s)) { + pop(a, n, i); + if (n < THRESHOLD) { + simplesort(a, n, i, tr, endch); + continue; + } + an = a + n; + + /* Make character histogram. */ + if (nc == 0) { + bmin = 255; /* First occupied bin, excluding eos. */ + for (ak = a; ak < an;) { + c = tr[(*ak++)[i]]; + if (++count[c] == 1 && c != endch) { + if (c < bmin) + bmin = c; + nc++; + } + } + if (sp + nc > s + SIZE) { /* Get more stack. */ + r_sort_a(a, n, i, tr, endch); + continue; + } + } + + /* + * Set top[]; push incompletely sorted bins onto stack. + * top[] = pointers to last out-of-place element in bins. + * count[] = counts of elements in bins. + * Before permuting: top[c-1] + count[c] = top[c]; + * during deal: top[c] counts down to top[c-1]. + */ + sp0 = sp1 = sp; /* Stack position of biggest bin. */ + bigc = 2; /* Size of biggest bin. */ + if (endch == 0) /* Special case: set top[eos]. */ + top[0] = ak = a + count[0]; + else { + ak = a; + top[255] = an; + } + for (cp = count + bmin; nc > 0; cp++) { + while (*cp == 0) /* Find next non-empty pile. */ + cp++; + if (*cp > 1) { + if (*cp > bigc) { + bigc = *cp; + sp1 = sp; + } + push(ak, *cp, i+1); + } + top[cp-count] = ak += *cp; + nc--; + } + swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */ + + /* + * Permute misplacements home. Already home: everything + * before aj, and in bin[c], items from top[c] on. + * Inner loop: + * r = next element to put in place; + * ak = top[r[i]] = location to put the next element. + * aj = bottom of 1st disordered bin. + * Outer loop: + * Once the 1st disordered bin is done, ie. aj >= ak, + * aj<-aj + count[c] connects the bins in a linked list; + * reset count[c]. + */ + for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0) + for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);) + swap(*ak, r, t); + } +} + +/* Stable sort, requiring additional memory. */ +static +void +r_sort_b(u_char const **a, u_char const **ta, int n, int i, u_char const *tr, u_int endch) +{ + static int count[256]; + static u_int nc; + static u_int bmin; + u_int c; + u_char const **ak, **ai; + stack s[512], *sp, *sp0, *sp1, temp; + u_char const **top[256]; + int *cp; + u_int bigc; + + sp = s; + push(a, n, i); + while (!empty(s)) { + pop(a, n, i); + if (n < THRESHOLD) { + simplesort(a, n, i, tr, endch); + continue; + } + + if (nc == 0) { + bmin = 255; + for (ak = a + n; --ak >= a;) { + c = tr[(*ak)[i]]; + if (++count[c] == 1 && c != endch) { + if (c < bmin) + bmin = c; + nc++; + } + } + if (sp + nc > s + SIZE) { + r_sort_b(a, ta, n, i, tr, endch); + continue; + } + } + + sp0 = sp1 = sp; + bigc = 2; + if (endch == 0) { + top[0] = ak = a + count[0]; + count[0] = 0; + } else { + ak = a; + top[255] = a + n; + count[255] = 0; + } + for (cp = count + bmin; nc > 0; cp++) { + while (*cp == 0) + cp++; + if ((c = *cp) > 1) { + if (c > bigc) { + bigc = c; + sp1 = sp; + } + push(ak, c, i+1); + } + top[cp-count] = ak += c; + *cp = 0; /* Reset count[]. */ + nc--; + } + swap(*sp0, *sp1, temp); + + for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */ + *--ak = *--ai; + for (ak = ta+n; --ak >= ta;) /* Deal to piles. */ + *--top[tr[(*ak)[i]]] = *ak; + } +} + +static inline +void +simplesort(u_char const **a, int n, int b, u_char const *tr, u_int endch) /* insertion sort */ +{ + u_char ch; + u_char const **ak; + u_char const **ai; + u_char const *s; + u_char const *t; + + for (ak = a+1; --n >= 1; ak++) { + for (ai = ak; ai > a; ai--) { + for (s = ai[0] + b, t = ai[-1] + b; + (ch = tr[*s]) != endch; s++, t++) + if (ch != tr[*t]) + break; + if (ch >= tr[*t]) + break; + swap(ai[0], ai[-1], s); + } + } +} diff --git a/src/kernel/libroot/posix/stdlib/rand.c b/src/kernel/libroot/posix/stdlib/rand.c new file mode 100644 index 0000000000..94f6b501ac --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/rand.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Posix rand_r function added May 1999 by Wes Peters . + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +#ifdef TEST +#include +#endif /* TEST */ + +static int +do_rand(unsigned long *ctx) +{ + return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1)); +} + + +int +rand_r(unsigned int *ctx) +{ + u_long val = (u_long) *ctx; + *ctx = do_rand(&val); + return (int) *ctx; +} + + +static u_long next = 1; + +int +rand() +{ + return do_rand(&next); +} + +void +srand(seed) +u_int seed; +{ + next = seed; +} + +#ifdef TEST + +main() +{ + int i; + unsigned myseed; + + printf("seeding rand with 0x19610910: \n"); + srand(0x19610910); + + printf("generating three pseudo-random numbers:\n"); + for (i = 0; i < 3; i++) + { + printf("next random number = %d\n", rand()); + } + + printf("generating the same sequence with rand_r:\n"); + myseed = 0x19610910; + for (i = 0; i < 3; i++) + { + printf("next random number = %d\n", rand_r(&myseed)); + } + + return 0; +} + +#endif /* TEST */ + diff --git a/src/kernel/libroot/posix/stdlib/random.c b/src/kernel/libroot/posix/stdlib/random.c new file mode 100644 index 0000000000..a9c84b9081 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/random.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/stdlib/random.c,v 1.13 2000/01/27 23:06:49 jasone Exp $ + * + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95"; +#endif /* LIBC_SCCS and not lint */ + +//#include /* for srandomdev() */ +//#include /* for srandomdev() */ +#include +#include +//#include /* for srandomdev() */ + +/* + * random.c: + * + * An improved random number generation package. In addition to the standard + * rand()/srand() like interface, this package also has a special state info + * interface. The initstate() routine is called with a seed, an array of + * bytes, and a count of how many bytes are being passed in; this array is + * then initialized to contain information for random number generation with + * that much state information. Good sizes for the amount of state + * information are 32, 64, 128, and 256 bytes. The state can be switched by + * calling the setstate() routine with the same array as was initiallized + * with initstate(). By default, the package runs with 128 bytes of state + * information and generates far better random numbers than a linear + * congruential generator. If the amount of state information is less than + * 32 bytes, a simple linear congruential R.N.G. is used. + * + * Internally, the state information is treated as an array of longs; the + * zeroeth element of the array is the type of R.N.G. being used (small + * integer); the remainder of the array is the state information for the + * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of + * state information, which will allow a degree seven polynomial. (Note: + * the zeroeth word of state information also has some other information + * stored in it -- see setstate() for details). + * + * The random number generation technique is a linear feedback shift register + * approach, employing trinomials (since there are fewer terms to sum up that + * way). In this approach, the least significant bit of all the numbers in + * the state table will act as a linear feedback shift register, and will + * have period 2^deg - 1 (where deg is the degree of the polynomial being + * used, assuming that the polynomial is irreducible and primitive). The + * higher order bits will have longer periods, since their values are also + * influenced by pseudo-random carries out of the lower bits. The total + * period of the generator is approximately deg*(2**deg - 1); thus doubling + * the amount of state information has a vast influence on the period of the + * generator. Note: the deg*(2**deg - 1) is an approximation only good for + * large deg, when the period of the shift register is the dominant factor. + * With deg equal to seven, the period is actually much longer than the + * 7*(2**7 - 1) predicted by this formula. + * + * Modified 28 December 1994 by Jacob S. Rosenberg. + * The following changes have been made: + * All references to the type u_int have been changed to unsigned long. + * All references to type int have been changed to type long. Other + * cleanups have been made as well. A warning for both initstate and + * setstate has been inserted to the effect that on Sparc platforms + * the 'arg_state' variable must be forced to begin on word boundaries. + * This can be easily done by casting a long integer array to char *. + * The overall logic has been left STRICTLY alone. This software was + * tested on both a VAX and Sun SpacsStation with exactly the same + * results. The new version and the original give IDENTICAL results. + * The new version is somewhat faster than the original. As the + * documentation says: "By default, the package runs with 128 bytes of + * state information and generates far better random numbers than a linear + * congruential generator. If the amount of state information is less than + * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of + * 128 bytes, this new version runs about 19 percent faster and for a 16 + * byte buffer it is about 5 percent faster. + */ + +/* + * For each of the currently supported random number generators, we have a + * break value on the amount of state information (you need at least this + * many bytes of state info to support this random number generator), a degree + * for the polynomial (actually a trinomial) that the R.N.G. is based on, and + * the separation between the two lower order coefficients of the trinomial. + */ +#define TYPE_0 0 /* linear congruential */ +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +#define TYPE_1 1 /* x**7 + x**3 + 1 */ +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +#define TYPE_2 2 /* x**15 + x + 1 */ +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +#define TYPE_3 3 /* x**31 + x**3 + 1 */ +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +#define TYPE_4 4 /* x**63 + x + 1 */ +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + +/* + * Array versions of the above information to make code run faster -- + * relies on fact that TYPE_i == i. + */ +#define MAX_TYPES 5 /* max number of types above */ + +//static long degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; +//static long seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; + +/* + * Initially, everything is set up as if from: + * + * initstate(1, randtbl, 128); + * + * Note that this initialization takes advantage of the fact that srandom() + * advances the front and rear pointers 10*rand_deg times, and hence the + * rear pointer which starts at 0 will also end up at zero; thus the zeroeth + * element of the state information, which contains info about the current + * position of the rear pointer is just + * + * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. + */ + +static long randtbl[DEG_3 + 1] = { + TYPE_3, +#ifdef USE_WEAK_SEEDING +/* Historic implementation compatibility */ +/* The random sequences do not vary much with the seed */ + 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, + 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, + 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, + 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, + 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, + 0x27fb47b9, +#else /* !USE_WEAK_SEEDING */ + 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05, + 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454, + 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471, + 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1, + 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41, + 0xf3bec5da +#endif /* !USE_WEAK_SEEDING */ +}; + +/* + * fptr and rptr are two pointers into the state info, a front and a rear + * pointer. These two pointers are always rand_sep places aparts, as they + * cycle cyclically through the state information. (Yes, this does mean we + * could get away with just one pointer, but the code for random() is more + * efficient this way). The pointers are left positioned as they would be + * from the call + * + * initstate(1, randtbl, 128); + * + * (The position of the rear pointer, rptr, is really 0 (as explained above + * in the initialization of randtbl) because the state table pointer is set + * to point to randtbl[1] (as explained below). + */ +static long *fptr = &randtbl[SEP_3 + 1]; +static long *rptr = &randtbl[1]; + +/* + * The following things are the pointer to the state information table, the + * type of the current generator, the degree of the current polynomial being + * used, and the separation between the two pointers. Note that for efficiency + * of random(), we remember the first location of the state information, not + * the zeroeth. Hence it is valid to access state[-1], which is used to + * store the type of the R.N.G. Also, we remember the last location, since + * this is more efficient than indexing every time to find the address of + * the last element to see if the front and rear pointers have wrapped. + */ +static long *state = &randtbl[1]; +static long rand_type = TYPE_3; +static long rand_deg = DEG_3; +static long rand_sep = SEP_3; +static long *end_ptr = &randtbl[DEG_3 + 1]; + +static inline long good_rand(long); + +static inline long good_rand(long x) +{ +#ifdef USE_WEAK_SEEDING +/* + * Historic implementation compatibility. + * The random sequences do not vary much with the seed, + * even with overflowing. + */ + return (1103515245 * x + 12345); +#else /* !USE_WEAK_SEEDING */ +/* + * Compute x = (7^5 * x) mod (2^31 - 1) + * wihout overflowing 31 bits: + * (2^31 - 1) = 127773 * (7^5) + 2836 + * From "Random number generators: good ones are hard to find", + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + register long hi, lo; + + hi = x / 127773; + lo = x % 127773; + x = 16807 * lo - 2836 * hi; + if (x <= 0) + x += 0x7fffffff; + return (x); +#endif /* !USE_WEAK_SEEDING */ +} + +/* + * srandom: + * + * Initialize the random number generator based on the given seed. If the + * type is the trivial no-state-information type, just remember the seed. + * Otherwise, initializes state[] based on the given "seed" via a linear + * congruential generator. Then, the pointers are set to known locations + * that are exactly rand_sep places apart. Lastly, it cycles the state + * information a given number of times to get rid of any initial dependencies + * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + * for default usage relies on values produced by this routine. + */ +void +srandom(unsigned long x) +{ + long i; + + if (rand_type == TYPE_0) { + state[0] = x; + } else { + state[0] = x; + for (i = 1; i < rand_deg; i++) { + state[i] = good_rand(state[i - 1]); + } + fptr = &state[rand_sep]; + rptr = &state[0]; + for (i = 0; i < 10 * rand_deg; i++) { + (void)random(); + } + } +} + +/* + * srandomdev: + * + * Many programs choose the seed value in a totally predictable manner. + * This often causes problems. We seed the generator using the much more + * secure urandom(4) interface. Note that this particular seeding + * procedure can generate states which are impossible to reproduce by + * calling srandom() with any value, since the succeeding terms in the + * state buffer are no longer derived from the LC algorithm applied to + * a fixed seed. + */ +#if 0 +/* not yet supported by NewOS */ +void +srandomdev() +{ + int fd, done; + size_t len; + + if (rand_type == TYPE_0) + len = sizeof state[0]; + else + len = rand_deg * sizeof state[0]; + + done = 0; + fd = _open("/dev/urandom", O_RDONLY, 0); + if (fd >= 0) { + if (_read(fd, (void *) state, len) == (ssize_t) len) + done = 1; + _close(fd); + } + + if (!done) { + struct timeval tv; + unsigned long junk; + + gettimeofday(&tv, NULL); + srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk); + return; + } + + if (rand_type != TYPE_0) { + fptr = &state[rand_sep]; + rptr = &state[0]; + } +} + +/* + * initstate: + * + * Initialize the state information in the given array of n bytes for future + * random number generation. Based on the number of bytes we are given, and + * the break values for the different R.N.G.'s, we choose the best (largest) + * one we can and set things up for it. srandom() is then called to + * initialize the state information. + * + * Note that on return from srandom(), we set state[-1] to be the type + * multiplexed with the current value of the rear pointer; this is so + * successive calls to initstate() won't lose this information and will be + * able to restart with setstate(). + * + * Note: the first thing we do is save the current state, if any, just like + * setstate() so that it doesn't matter when initstate is called. + * + * Returns a pointer to the old state. + * + * Note: The Sparc platform requires that arg_state begin on a long + * word boundary; otherwise a bus error will occur. Even so, lint will + * complain about mis-alignment, but you should disregard these messages. + */ +char * +initstate(seed, arg_state, n) + unsigned long seed; /* seed for R.N.G. */ + char *arg_state; /* pointer to state array */ + long n; /* # bytes of state info */ +{ + register char *ostate = (char *)(&state[-1]); + register long *long_arg_state = (long *) arg_state; + + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = MAX_TYPES * (rptr - state) + rand_type; + if (n < BREAK_0) { + (void)fprintf(stderr, + "random: not enough state (%ld bytes); ignored.\n", n); + return(0); + } + if (n < BREAK_1) { + rand_type = TYPE_0; + rand_deg = DEG_0; + rand_sep = SEP_0; + } else if (n < BREAK_2) { + rand_type = TYPE_1; + rand_deg = DEG_1; + rand_sep = SEP_1; + } else if (n < BREAK_3) { + rand_type = TYPE_2; + rand_deg = DEG_2; + rand_sep = SEP_2; + } else if (n < BREAK_4) { + rand_type = TYPE_3; + rand_deg = DEG_3; + rand_sep = SEP_3; + } else { + rand_type = TYPE_4; + rand_deg = DEG_4; + rand_sep = SEP_4; + } + state = (long *) (long_arg_state + 1); /* first location */ + end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ + srandom(seed); + if (rand_type == TYPE_0) + long_arg_state[0] = rand_type; + else + long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type; + return(ostate); +} + +/* + * setstate: + * + * Restore the state from the given state array. + * + * Note: it is important that we also remember the locations of the pointers + * in the current state information, and restore the locations of the pointers + * from the old state information. This is done by multiplexing the pointer + * location into the zeroeth word of the state information. + * + * Note that due to the order in which things are done, it is OK to call + * setstate() with the same state as the current state. + * + * Returns a pointer to the old state information. + * + * Note: The Sparc platform requires that arg_state begin on a long + * word boundary; otherwise a bus error will occur. Even so, lint will + * complain about mis-alignment, but you should disregard these messages. + */ +char * +setstate(arg_state) + char *arg_state; /* pointer to state array */ +{ + register long *new_state = (long *) arg_state; + register long type = new_state[0] % MAX_TYPES; + register long rear = new_state[0] / MAX_TYPES; + char *ostate = (char *)(&state[-1]); + + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = MAX_TYPES * (rptr - state) + rand_type; + switch(type) { + case TYPE_0: + case TYPE_1: + case TYPE_2: + case TYPE_3: + case TYPE_4: + rand_type = type; + rand_deg = degrees[type]; + rand_sep = seps[type]; + break; + default: + (void)fprintf(stderr, + "random: state info corrupted; not changed.\n"); + } + state = (long *) (new_state + 1); + if (rand_type != TYPE_0) { + rptr = &state[rear]; + fptr = &state[(rear + rand_sep) % rand_deg]; + } + end_ptr = &state[rand_deg]; /* set end_ptr too */ + return(ostate); +} +#endif + +/* + * random: + * + * If we are using the trivial TYPE_0 R.N.G., just do the old linear + * congruential bit. Otherwise, we do our fancy trinomial stuff, which is + * the same in all the other cases due to all the global variables that have + * been set up. The basic operation is to add the number at the rear pointer + * into the one at the front pointer. Then both pointers are advanced to + * the next location cyclically in the table. The value returned is the sum + * generated, reduced to 31 bits by throwing away the "least random" low bit. + * + * Note: the code takes advantage of the fact that both the front and + * rear pointers can't wrap on the same call by not testing the rear + * pointer if the front one has wrapped. + * + * Returns a 31-bit random number. + */ +long +random(void) +{ + long i; + long *f; + long *r; + + if (rand_type == TYPE_0) { + i = state[0]; + state[0] = i = (good_rand(i)) & 0x7fffffff; + } else { + /* + * Use local variables rather than static variables for speed. + */ + f = fptr; r = rptr; + *f += *r; + i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */ + if (++f >= end_ptr) { + f = state; + ++r; + } + else if (++r >= end_ptr) { + r = state; + } + + fptr = f; rptr = r; + } + return(i); +} diff --git a/src/kernel/libroot/posix/stdlib/realpath.c b/src/kernel/libroot/posix/stdlib/realpath.c new file mode 100644 index 0000000000..8c5a3187da --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/realpath.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include + +#include +#include +#include +#include +#include + + +/** Find the real name of path, by removing all ".", ".." and symlink + * components. Returns (resolved) on success, or (NULL) on failure, + * in which case the path which caused trouble is left in (resolved). + */ + +char * +realpath(const char *path, char *resolved) +{ + struct stat sb; + int fd, n, rootd, serrno; + char *p, *q, wbuf[MAXPATHLEN]; + int symlinks = 0; + + /* Save the starting point. */ + if ((fd = open(".", O_RDONLY)) < 0) { + strcpy(resolved, "."); + return NULL; + } + + /* + * Find the dirname and basename from the path to be resolved. + * Change directory to the dirname component. + * lstat the basename part. + * if it is a symlink, read in the value and loop. + * if it is a directory, then change to that directory. + * get the current directory name and append the basename. + */ + strncpy(resolved, path, MAXPATHLEN - 1); + resolved[MAXPATHLEN - 1] = '\0'; + +loop: + q = strrchr(resolved, '/'); + if (q != NULL) { + p = q + 1; + if (q == resolved) + q = "/"; + else { + do { + --q; + } while (q > resolved && *q == '/'); + q[1] = '\0'; + q = resolved; + } + if (chdir(q) < 0) + goto err1; + } else + p = resolved; + + /* Deal with the last component. */ + if (*p != '\0' && lstat(p, &sb) == 0) { + if (S_ISLNK(sb.st_mode)) { + if (++symlinks > MAXSYMLINKS) { + errno = ELOOP; + goto err1; + } + n = readlink(p, resolved, MAXPATHLEN - 1); + if (n < 0) + goto err1; + resolved[n] = '\0'; + goto loop; + } + if (S_ISDIR(sb.st_mode)) { + if (chdir(p) < 0) + goto err1; + p = ""; + } + } + + /* + * Save the last component name and get the full pathname of + * the current directory. + */ + strcpy(wbuf, p); + if (getcwd(resolved, MAXPATHLEN) == 0) + goto err1; + + /* + * Join the two strings together, ensuring that the right thing + * happens if the last component is empty, or the dirname is root. + */ + if (resolved[0] == '/' && resolved[1] == '\0') + rootd = 1; + else + rootd = 0; + + if (*wbuf) { + if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { + errno = ENAMETOOLONG; + goto err1; + } + if (rootd == 0) + strcat(resolved, "/"); + strcat(resolved, wbuf); + } + + /* Go back to where we came from. */ + if (fchdir(fd) < 0) { + serrno = errno; + goto err2; + } + + /* It's okay if the close fails, what's an fd more or less? */ + close(fd); + return resolved; + +err1: + serrno = errno; + fchdir(fd); +err2: + close(fd); + errno = serrno; + return NULL; +} diff --git a/src/kernel/libroot/posix/stdlib/strtoq.c b/src/kernel/libroot/posix/stdlib/strtoq.c new file mode 100644 index 0000000000..b15f8090a4 --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/strtoq.c @@ -0,0 +1,150 @@ +/*- + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +//#include +#include + +#define QUAD_MIN (-0x7fffffffffffffffLL - 1) +#define QUAD_MAX 0x7fffffffffffffffLL +/* + * Convert a string to a quad integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +int64 +strtoq(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register const char *s; + register int64 acc, cutoff; + register int c; + register int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = (unsigned char) *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? QUAD_MIN : QUAD_MAX; + cutlim = cutoff % base; + cutoff /= base; + if (neg) { + if (cutlim > 0) { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } + for (acc = 0, any = 0;; c = (unsigned char) *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0) + continue; + if (neg) { + if (acc < cutoff || (acc == cutoff && c > cutlim)) { + any = -1; + acc = QUAD_MIN; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc -= c; + } + } else { + if (acc > cutoff || (acc == cutoff && c > cutlim)) { + any = -1; + acc = QUAD_MAX; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc += c; + } + } + } + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} diff --git a/src/kernel/libroot/posix/stdlib/strtouq.c b/src/kernel/libroot/posix/stdlib/strtouq.c new file mode 100644 index 0000000000..4d695eefef --- /dev/null +++ b/src/kernel/libroot/posix/stdlib/strtouq.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +//#include +#include + +#define UQUAD_MAX 0xffffffffffffffffULL +/* + * Convert a string to an unsigned quad integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +uint64 +strtouq(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register const char *s; + register uint64 acc, cutoff; + register int c; + register int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = (unsigned char) *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + cutoff = UQUAD_MAX / (uint64)base; + cutlim = UQUAD_MAX % (uint64)base; + for (acc = 0, any = 0;; c = (unsigned char) *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0) + continue; + if (acc > cutoff || (acc == cutoff && c > cutlim)) { + any = -1; + acc = UQUAD_MAX; + errno = ERANGE; + } else { + any = 1; + acc *= (uint64)base; + acc += c; + } + } + if (neg && any > 0) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} diff --git a/src/kernel/libroot/posix/string/Jamfile b/src/kernel/libroot/posix/string/Jamfile new file mode 100644 index 0000000000..961a912294 --- /dev/null +++ b/src/kernel/libroot/posix/string/Jamfile @@ -0,0 +1,33 @@ +SubDir OBOS_TOP src kernel libroot posix string ; + +KernelObjects + <$(SOURCE_GRIST)>memchr.c + <$(SOURCE_GRIST)>memcmp.c + <$(SOURCE_GRIST)>memcpy.c + <$(SOURCE_GRIST)>memmove.c + <$(SOURCE_GRIST)>memset.c + <$(SOURCE_GRIST)>strcasecmp.c + <$(SOURCE_GRIST)>strcasestr.c + <$(SOURCE_GRIST)>strcat.c + <$(SOURCE_GRIST)>strchr.c + <$(SOURCE_GRIST)>strcmp.c + <$(SOURCE_GRIST)>strcpy.c + <$(SOURCE_GRIST)>strcspn.c + <$(SOURCE_GRIST)>strdup.c + <$(SOURCE_GRIST)>strerror.c + <$(SOURCE_GRIST)>strlcat.c + <$(SOURCE_GRIST)>strlcpy.c + <$(SOURCE_GRIST)>strlen.c + <$(SOURCE_GRIST)>strncat.c + <$(SOURCE_GRIST)>strncmp.c + <$(SOURCE_GRIST)>strncpy.c + <$(SOURCE_GRIST)>strnicmp.c + <$(SOURCE_GRIST)>strnlen.c + <$(SOURCE_GRIST)>strpbrk.c + <$(SOURCE_GRIST)>strrchr.c + <$(SOURCE_GRIST)>strspn.c + <$(SOURCE_GRIST)>strstr.c + <$(SOURCE_GRIST)>strtok.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/string/arch/ppc/libc.mk b/src/kernel/libroot/posix/string/arch/ppc/libc.mk new file mode 100644 index 0000000000..5925d910cd --- /dev/null +++ b/src/kernel/libroot/posix/string/arch/ppc/libc.mk @@ -0,0 +1,24 @@ +LIBC_ARCH_DIR = $(LIBC_DIR)/arch/$(ARCH) +LIBC_ARCH_OBJ_DIR = $(LIBC_ARCH_DIR)/$(OBJ_DIR) + +LIBC_OBJS += + +# build prototypes +$(LIBC_ARCH_OBJ_DIR)/%.o: $(LIBC_ARCH_DIR)/%.c + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + $(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -o $@ + +$(LIBC_ARCH_OBJ_DIR)/%.d: $(LIBC_ARCH_DIR)/%.c + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + @echo "making deps for $<..." + @($(ECHO) -n $(dir $@); $(CC) $(GLOBAL_CFLAGS) -Iinclude -M -MG $<) > $@ + +$(LIBC_ARCH_OBJ_DIR)/%.d: $(LIBC_ARCH_DIR)/%.S + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + @echo "making deps for $<..." + @($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -M -MG $<) > $@ + +$(LIBC_ARCH_OBJ_DIR)/%.o: $(LIBC_ARCH_DIR)/%.S + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + $(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -o $@ + diff --git a/src/kernel/libroot/posix/string/arch/sh4/libc.mk b/src/kernel/libroot/posix/string/arch/sh4/libc.mk new file mode 100644 index 0000000000..5925d910cd --- /dev/null +++ b/src/kernel/libroot/posix/string/arch/sh4/libc.mk @@ -0,0 +1,24 @@ +LIBC_ARCH_DIR = $(LIBC_DIR)/arch/$(ARCH) +LIBC_ARCH_OBJ_DIR = $(LIBC_ARCH_DIR)/$(OBJ_DIR) + +LIBC_OBJS += + +# build prototypes +$(LIBC_ARCH_OBJ_DIR)/%.o: $(LIBC_ARCH_DIR)/%.c + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + $(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -o $@ + +$(LIBC_ARCH_OBJ_DIR)/%.d: $(LIBC_ARCH_DIR)/%.c + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + @echo "making deps for $<..." + @($(ECHO) -n $(dir $@); $(CC) $(GLOBAL_CFLAGS) -Iinclude -M -MG $<) > $@ + +$(LIBC_ARCH_OBJ_DIR)/%.d: $(LIBC_ARCH_DIR)/%.S + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + @echo "making deps for $<..." + @($(ECHO) -n $(dir $@);$(CC) $(GLOBAL_CFLAGS) -Iinclude -M -MG $<) > $@ + +$(LIBC_ARCH_OBJ_DIR)/%.o: $(LIBC_ARCH_DIR)/%.S + @if [ ! -d $(LIBC_ARCH_OBJ_DIR) ]; then mkdir -p $(LIBC_ARCH_OBJ_DIR); fi + $(CC) -c $< $(GLOBAL_CFLAGS) -Iinclude -o $@ + diff --git a/src/kernel/libroot/posix/string/arch/x86/memcpy.S b/src/kernel/libroot/posix/string/arch/x86/memcpy.S new file mode 100644 index 0000000000..0bd67b39d0 --- /dev/null +++ b/src/kernel/libroot/posix/string/arch/x86/memcpy.S @@ -0,0 +1,32 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include + +.globl memcpy + +.align 4 +memcpy: + pushl %esi + pushl %edi + movl 12(%esp),%edi /* dest */ + movl %edi,%eax /* save dest ptr as return address */ + movl 16(%esp),%esi /* source */ + movl 20(%esp),%ecx /* count */ + + /* move by words */ + cld + shrl $2,%ecx + rep + movsl + + /* move any remaining data by bytes */ + movl 20(%esp),%ecx + andl $3,%ecx + rep + movsb + + popl %edi + popl %esi + ret diff --git a/src/kernel/libroot/posix/string/bcopy.c b/src/kernel/libroot/posix/string/bcopy.c new file mode 100644 index 0000000000..3507c84972 --- /dev/null +++ b/src/kernel/libroot/posix/string/bcopy.c @@ -0,0 +1,14 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + +void * +bcopy(void const *src, void *dest, size_t count) +{ + return memcpy(dest, src, count); +} + diff --git a/src/kernel/libroot/posix/string/bzero.c b/src/kernel/libroot/posix/string/bzero.c new file mode 100644 index 0000000000..8630c966a4 --- /dev/null +++ b/src/kernel/libroot/posix/string/bzero.c @@ -0,0 +1,14 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + +void +bzero(void *dst, size_t count) +{ + memset(dst, 0, count); +} + diff --git a/src/kernel/libroot/posix/string/memchr.c b/src/kernel/libroot/posix/string/memchr.c new file mode 100644 index 0000000000..442b026556 --- /dev/null +++ b/src/kernel/libroot/posix/string/memchr.c @@ -0,0 +1,24 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +void * +memchr(void const *buf, int c, size_t len) +{ + unsigned char const *b = buf; + unsigned char x = (c&0xff); + size_t i; + + for (i = 0; i < len; i++) { + if (b[i] == x) + return (void*)(b + i); + } + + return NULL; +} + diff --git a/src/kernel/libroot/posix/string/memcmp.c b/src/kernel/libroot/posix/string/memcmp.c new file mode 100644 index 0000000000..982e47fbb5 --- /dev/null +++ b/src/kernel/libroot/posix/string/memcmp.c @@ -0,0 +1,20 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +int +memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1, *su2; + signed char res = 0; + + for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} diff --git a/src/kernel/libroot/posix/string/memcpy.c b/src/kernel/libroot/posix/string/memcpy.c new file mode 100644 index 0000000000..501507acec --- /dev/null +++ b/src/kernel/libroot/posix/string/memcpy.c @@ -0,0 +1,48 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +#if !_ASM_MEMCPY + +typedef int word; + +#define lsize sizeof(word) +#define lmask (lsize - 1) + +void *memcpy(void *dest, const void *src, size_t count) +{ + char *d = (char *)dest; + const char *s = (const char *)src; + int len; + + if(count == 0 || dest == src) + return dest; + + if(((long)d | (long)s) & lmask) { + // src and/or dest do not align on word boundary + if((((long)d ^ (long)s) & lmask) || (count < lsize)) + len = count; // copy the rest of the buffer with the byte mover + else + len = lsize - ((long)d & lmask); // move the ptrs up to a word boundary + + count -= len; + for(; len > 0; len--) + *d++ = *s++; + } + for(len = count / lsize; len > 0; len--) { + *(word *)d = *(word *)s; + d += lsize; + s += lsize; + } + for(len = count & lmask; len > 0; len--) + *d++ = *s++; + + return dest; +} + +#endif diff --git a/src/kernel/libroot/posix/string/memmove.c b/src/kernel/libroot/posix/string/memmove.c new file mode 100644 index 0000000000..d0ec2c4be9 --- /dev/null +++ b/src/kernel/libroot/posix/string/memmove.c @@ -0,0 +1,72 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + +#if !_ASM_MEMCPY + +typedef int word; + +#define lsize sizeof(word) +#define lmask (lsize - 1) + +void * +memmove(void *dest, void const *src, size_t count) +{ + char *d = (char *)dest; + const char *s = (const char *)src; + int len; + + if(count == 0 || dest == src) + return dest; + + if((long)d < (long)s) { + if(((long)d | (long)s) & lmask) { + // src and/or dest do not align on word boundary + if((((long)d ^ (long)s) & lmask) || (count < lsize)) + len = count; // copy the rest of the buffer with the byte mover + else + len = lsize - ((long)d & lmask); // move the ptrs up to a word boundary + + count -= len; + for(; len > 0; len--) + *d++ = *s++; + } + for(len = count / lsize; len > 0; len--) { + *(word *)d = *(word *)s; + d += lsize; + s += lsize; + } + for(len = count & lmask; len > 0; len--) + *d++ = *s++; + } else { + d += count; + s += count; + if(((long)d | (long)s) & lmask) { + // src and/or dest do not align on word boundary + if((((long)d ^ (long)s) & lmask) || (count <= lsize)) + len = count; + else + len = ((long)d & lmask); + + count -= len; + for(; len > 0; len--) + *--d = *--s; + } + for(len = count / lsize; len > 0; len--) { + d -= lsize; + s -= lsize; + *(word *)d = *(word *)s; + } + for(len = count & lmask; len > 0; len--) + *--d = *--s; + } + + return dest; +} + +#endif + diff --git a/src/kernel/libroot/posix/string/memset.c b/src/kernel/libroot/posix/string/memset.c new file mode 100644 index 0000000000..68166576a7 --- /dev/null +++ b/src/kernel/libroot/posix/string/memset.c @@ -0,0 +1,19 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +void * +memset(void *s, int c, size_t count) +{ + char *xs = (char *) s; + + while (count--) + *xs++ = c; + + return s; +} diff --git a/src/kernel/libroot/posix/string/strcasecmp.c b/src/kernel/libroot/posix/string/strcasecmp.c new file mode 100644 index 0000000000..d584ddd7dc --- /dev/null +++ b/src/kernel/libroot/posix/string/strcasecmp.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include + +//typedef unsigned char u_char; + + +int +strcasecmp(const char *s1, const char *s2) +{ + const u_char *us1 = (const u_char *)s1; + const u_char *us2 = (const u_char *)s2; + + while (tolower(*us1) == tolower(*us2++)) + if (*us1++ == '\0') + return 0; + + return tolower(*us1) - tolower(*--us2); +} + + +int +strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n != 0) { + const u_char *us1 = (const u_char *)s1; + const u_char *us2 = (const u_char *)s2; + + do { + if (tolower(*us1) != tolower(*us2++)) + return tolower(*us1) - tolower(*--us2); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return 0; +} + diff --git a/src/kernel/libroot/posix/string/strcasestr.c b/src/kernel/libroot/posix/string/strcasestr.c new file mode 100644 index 0000000000..d6a5710f09 --- /dev/null +++ b/src/kernel/libroot/posix/string/strcasestr.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + + +/* + * Find the first occurrence of find in s, ignore case. + */ + +char * +strcasestr(const char *s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = tolower((unsigned char)c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return NULL; + } while ((char)tolower((unsigned char)sc) != c); + } while (strncasecmp(s, find, len) != 0); + s--; + } + return (char *)s; +} + diff --git a/src/kernel/libroot/posix/string/strcat.c b/src/kernel/libroot/posix/string/strcat.c new file mode 100644 index 0000000000..3323583156 --- /dev/null +++ b/src/kernel/libroot/posix/string/strcat.c @@ -0,0 +1,22 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strcat(char *dest, char const*src) +{ + char *tmp = dest; + + while(*dest) + dest++; + while((*dest++ = *src++) != '\0') + ; + + return tmp; +} + diff --git a/src/kernel/libroot/posix/string/strchr.c b/src/kernel/libroot/posix/string/strchr.c new file mode 100644 index 0000000000..a914b961d4 --- /dev/null +++ b/src/kernel/libroot/posix/string/strchr.c @@ -0,0 +1,18 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strchr(const char *s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *)s; +} + diff --git a/src/kernel/libroot/posix/string/strcmp.c b/src/kernel/libroot/posix/string/strcmp.c new file mode 100644 index 0000000000..38a9cac7f2 --- /dev/null +++ b/src/kernel/libroot/posix/string/strcmp.c @@ -0,0 +1,21 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +int +strcmp(char const *cs, char const *ct) +{ + signed char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + } + + return __res; +} diff --git a/src/kernel/libroot/posix/string/strcpy.c b/src/kernel/libroot/posix/string/strcpy.c new file mode 100644 index 0000000000..f4e8140c9f --- /dev/null +++ b/src/kernel/libroot/posix/string/strcpy.c @@ -0,0 +1,19 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strcpy(char *dest, char const *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') + ; + return tmp; +} + diff --git a/src/kernel/libroot/posix/string/strcspn.c b/src/kernel/libroot/posix/string/strcspn.c new file mode 100644 index 0000000000..c052485b80 --- /dev/null +++ b/src/kernel/libroot/posix/string/strcspn.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + + +/* + * Span the complement of string s2. + */ + +size_t +strcspn(const char *s1, const char *s2) +{ + const char *p, *spanp; + char c, sc; + + /* + * Stop as soon as we find any character from s2. Note that there + * must be a NUL in s2; it suffices to stop when we find that, too. + */ + for (p = s1;;) { + c = *p++; + spanp = s2; + do { + if ((sc = *spanp++) == c) + return (p - 1 - s1); + } while (sc != 0); + } + /* NOTREACHED */ +} + diff --git a/src/kernel/libroot/posix/string/strdup.c b/src/kernel/libroot/posix/string/strdup.c new file mode 100644 index 0000000000..50f839af29 --- /dev/null +++ b/src/kernel/libroot/posix/string/strdup.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include + + +char * +strdup(const char *str) +{ + size_t len; + char *copy; + + len = strlen(str) + 1; + if ((copy = malloc(len)) == NULL) + return NULL; + + memcpy(copy, str, len); + return copy; +} + diff --git a/src/kernel/libroot/posix/string/strerror.c b/src/kernel/libroot/posix/string/strerror.c new file mode 100644 index 0000000000..23d8c90e2b --- /dev/null +++ b/src/kernel/libroot/posix/string/strerror.c @@ -0,0 +1,209 @@ +/* +** Copyright 2001, Dan Sinclair. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include +#include +#include + + +char const * +strerror(int errnum) +{ + switch (errnum) { + /* General Errors */ + case B_NO_ERROR: + return "No Error"; + + case ERR_GENERAL: + return "General Error"; + + // B_INTERRUPTED + case EINTR: + return "Interrupted"; + + // B_NO_MEMORY: + case ENOMEM: + return "Cannot allocate memory"; + + case ERR_IO_ERROR: + return "Input/Output error"; + + case EINVAL: + return "Invalid Arguments"; + +// case ERR_TIMED_OUT: + case ETIMEDOUT: + return "Timed out"; + +// case ERR_NOT_ALLOWED: + case EPERM: + return "Operation not permitted"; + +// case ERR_PERMISSION_DENIED: + case EACCES: + return "Operation not permitted"; + + case ERR_INVALID_BINARY: + return "Invalid Binary"; + + case ERR_INVALID_HANDLE: + return "Invalid ID Handle"; + + /* EMFILE */ + case ERR_NO_MORE_HANDLES: + return "No more handles"; + + case EBADF: + return "Bad file descriptor"; + + case ENOENT: + return "No such file or directory"; + + case ENFILE: + return "Too many open files in system"; + + case EMFILE: + return "Too many open files"; + + case ENXIO: + return "Device not configured"; + + case ESPIPE: + return "Illegal seek"; + +// case ERR_UNIMPLEMENTED: + case ENOSYS: + return "Unimplemented"; + +// case ERR_TOO_BIG: + case EDOM: + return "Numerical argument out of range"; + + case ERR_NOT_FOUND: + return "Not found"; + + case ERR_NOT_IMPLEMENTED_YET: + return "Not implemented yet"; + + + /* Semaphore errors */ + case B_BAD_SEM_ID: + return "Bad sem id"; + + case B_NO_MORE_SEMS: + return "Semaphore out of slots"; + + case ERR_SEM_NOT_INTERRUPTABLE: + return "Semaphore not interruptable"; + + /* Tasker errors */ + case ERR_TASK_GENERAL: + return "General Tasker error"; + + case ERR_TASK_PROC_DELETED: + return "Tasker process deleted"; + + /* VFS errors */ + case ERR_VFS_GENERAL: + return "General VFS error"; + + case ERR_VFS_INVALID_FS: + return "VFS invalid filesystem"; + + case ERR_VFS_NOT_MOUNTPOINT: + return "VFS not a mount point"; + + case ERR_VFS_PATH_NOT_FOUND: + return "VFS path not found"; + +// case ERR_VFS_INSUFFICIENT_BUF: + case ENOBUFS: + return "VFS insufficient buffer"; + +// case ERR_VFS_READONLY_FS: + case EROFS: + return "VFS readonly filesystem"; + +// case ERR_VFS_ALREADY_EXISTS: + case EEXIST: + return "VFS already exists"; + +// case ERR_VFS_FS_BUSY: + case EBUSY: + return "Device busy"; + + case ERR_VFS_FD_TABLE_FULL: + return "VFS file descriptor table full"; + + case ERR_VFS_CROSS_FS_RENAME: + return "VFS cross filesystem rename"; + + case ERR_VFS_DIR_NOT_EMPTY: + return "Directory not empty"; + +// case ERR_VFS_NOT_DIR: + case ENOTDIR: + return "Not a directory"; + + case ERR_VFS_WRONG_STREAM_TYPE: + return "VFS wrong stream type"; + + case ERR_VFS_ALREADY_MOUNTPOINT: + return "VFS already a mount point"; + + /* VM errors */ + case ERR_VM_GENERAL: + return "General VM error"; + + case ERR_VM_INVALID_ASPACE: + return "VM invalid aspace"; + + case ERR_VM_INVALID_REGION: + return "VM invalid region"; + + case ERR_VM_BAD_ADDRESS: + return "VM bad address"; + + case ERR_VM_PF_FATAL: + return "VM PF fatal"; + + case ERR_VM_PF_BAD_ADDRESS: + return "VM PF bad address"; + + case ERR_VM_PF_BAD_PERM: + return "VM PF bad permissions"; + + case ERR_VM_PAGE_NOT_PRESENT: + return "VM page not present"; + + case ERR_VM_NO_REGION_SLOT: + return "VM no region slot"; + + case ERR_VM_WOULD_OVERCOMMIT: + return "VM would overcommit"; + + case ERR_VM_BAD_USER_MEMORY: + return "VM bad user memory"; + + /* Elf errors */ + case ERR_ELF_GENERAL: + return "General ELF error"; + + case ERR_ELF_RESOLVING_SYMBOL: + return "ELF resolving symbol"; + + /* Ports errors */ + case B_BAD_PORT_ID: + return "Port does not exist"; + + case B_NO_MORE_PORTS: + return "No more ports available"; + + default: + return "Unknown error"; + } +} + diff --git a/src/kernel/libroot/posix/string/strlcat.c b/src/kernel/libroot/posix/string/strlcat.c new file mode 100644 index 0000000000..68439eb3d7 --- /dev/null +++ b/src/kernel/libroot/posix/string/strlcat.c @@ -0,0 +1,27 @@ +/* +** Copyright 2002, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +size_t +strlcat(char *dst, char const *src, size_t s) +{ + size_t i, j = strnlen(dst, s); + + if (!s) + return j + strlen(src); + + dst += j; + + for (i = 0; ((i < s-1) && src[i]); i++) { + dst[i] = src[i]; + } + + dst[i] = 0; + + return j + i + strlen(src + i); +} diff --git a/src/kernel/libroot/posix/string/strlcpy.c b/src/kernel/libroot/posix/string/strlcpy.c new file mode 100644 index 0000000000..04e387b2c2 --- /dev/null +++ b/src/kernel/libroot/posix/string/strlcpy.c @@ -0,0 +1,25 @@ +/* +** Copyright 2002, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +size_t +strlcpy(char *dst, char const *src, size_t s) +{ + size_t i= 0; + + if (!s) + return strlen(src); + + for (i = 0; ((i < s - 1) && src[i]); i++) { + dst[i] = src[i]; + } + + dst[i] = 0; + + return i + strlen(src + i); +} diff --git a/src/kernel/libroot/posix/string/strlen.c b/src/kernel/libroot/posix/string/strlen.c new file mode 100644 index 0000000000..08e0d9a037 --- /dev/null +++ b/src/kernel/libroot/posix/string/strlen.c @@ -0,0 +1,20 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +size_t +strlen(char const *s) +{ + size_t i = 0; + + while (s[i]) { + i += 1; + } + + return i; +} diff --git a/src/kernel/libroot/posix/string/strncat.c b/src/kernel/libroot/posix/string/strncat.c new file mode 100644 index 0000000000..ae4b757fb9 --- /dev/null +++ b/src/kernel/libroot/posix/string/strncat.c @@ -0,0 +1,28 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strncat(char *dest, char const *src, size_t count) +{ + char *tmp = dest; + + if (count > 0) { + while (*dest) + dest++; + while ((*dest++ = *src++)) { + if (--count == 0) { + *dest = '\0'; + break; + } + } + } + + return tmp; +} + diff --git a/src/kernel/libroot/posix/string/strncmp.c b/src/kernel/libroot/posix/string/strncmp.c new file mode 100644 index 0000000000..1bb7718476 --- /dev/null +++ b/src/kernel/libroot/posix/string/strncmp.c @@ -0,0 +1,22 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +int +strncmp(char const *cs, char const *ct, size_t count) +{ + signed char __res = 0; + + while (count > 0) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} diff --git a/src/kernel/libroot/posix/string/strncpy.c b/src/kernel/libroot/posix/string/strncpy.c new file mode 100644 index 0000000000..ff3b1593f5 --- /dev/null +++ b/src/kernel/libroot/posix/string/strncpy.c @@ -0,0 +1,20 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strncpy(char *dest, char const *src, size_t count) +{ + char *tmp = dest; + + while (count-- && (*dest++ = *src++) != '\0') + ; + + return tmp; +} + diff --git a/src/kernel/libroot/posix/string/strnicmp.c b/src/kernel/libroot/posix/string/strnicmp.c new file mode 100644 index 0000000000..6b2a65c35a --- /dev/null +++ b/src/kernel/libroot/posix/string/strnicmp.c @@ -0,0 +1,35 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include +#include + + +int +strnicmp(char const *s1, char const *s2, size_t len) +{ + unsigned char c1 = '\0'; + unsigned char c2 = '\0'; + + if (len > 0) { + do { + c1 = *s1; c2 = *s2; + s1++; s2++; + if (!c1) + break; + if (!c2) + break; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; + } while (--len); + } + return (int)c1 - (int)c2; +} +#pragma weak strncasecmp=strnicmp diff --git a/src/kernel/libroot/posix/string/strnlen.c b/src/kernel/libroot/posix/string/strnlen.c new file mode 100644 index 0000000000..573b36527e --- /dev/null +++ b/src/kernel/libroot/posix/string/strnlen.c @@ -0,0 +1,18 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +size_t +strnlen(char const *s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + ; + return sc - s; +} diff --git a/src/kernel/libroot/posix/string/strpbrk.c b/src/kernel/libroot/posix/string/strpbrk.c new file mode 100644 index 0000000000..b765d44e10 --- /dev/null +++ b/src/kernel/libroot/posix/string/strpbrk.c @@ -0,0 +1,24 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strpbrk(char const *cs, char const *ct) +{ + const char *sc1; + const char *sc2; + + for (sc1 = cs; *sc1 != '\0'; ++sc1) { + for (sc2 = ct; *sc2 != '\0'; ++sc2) { + if (*sc1 == *sc2) + return (char *)sc1; + } + } + + return NULL; +} diff --git a/src/kernel/libroot/posix/string/strrchr.c b/src/kernel/libroot/posix/string/strrchr.c new file mode 100644 index 0000000000..be8ab086c0 --- /dev/null +++ b/src/kernel/libroot/posix/string/strrchr.c @@ -0,0 +1,24 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strrchr(char const *s, int c) +{ + char const *last = c ? 0 : s; + + + while (*s) { + if (*s == c) + last = s; + + s += 1; + } + + return (char *)last; +} diff --git a/src/kernel/libroot/posix/string/strspn.c b/src/kernel/libroot/posix/string/strspn.c new file mode 100644 index 0000000000..c13e7045d0 --- /dev/null +++ b/src/kernel/libroot/posix/string/strspn.c @@ -0,0 +1,28 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +size_t +strspn(char const *s, char const *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (a = accept; *a != '\0'; ++a) { + if (*p == *a) + break; + } + if (*a == '\0') + return count; + ++count; + } + + return count; +} diff --git a/src/kernel/libroot/posix/string/strstr.c b/src/kernel/libroot/posix/string/strstr.c new file mode 100644 index 0000000000..44871f461d --- /dev/null +++ b/src/kernel/libroot/posix/string/strstr.c @@ -0,0 +1,26 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +char * +strstr(char const *s1, char const *s2) +{ + int l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *)s1; + l1 = strlen(s1); + while (l1 >= l2) { + l1--; + if (!memcmp(s1,s2,l2)) + return (char *)s1; + s1++; + } + return NULL; +} diff --git a/src/kernel/libroot/posix/string/strtok.c b/src/kernel/libroot/posix/string/strtok.c new file mode 100644 index 0000000000..d5538d3f7d --- /dev/null +++ b/src/kernel/libroot/posix/string/strtok.c @@ -0,0 +1,32 @@ +/* +** Copyright 2001, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +static char *___strtok = NULL; + +char * +strtok(char *s, char const *ct) +{ + char *sbegin, *send; + + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return NULL; + } + send = strpbrk(sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + + return sbegin; +} diff --git a/src/kernel/libroot/posix/sys/Jamfile b/src/kernel/libroot/posix/sys/Jamfile new file mode 100644 index 0000000000..80ef9891c6 --- /dev/null +++ b/src/kernel/libroot/posix/sys/Jamfile @@ -0,0 +1,10 @@ +SubDir OBOS_TOP src kernel libroot posix sys ; + +KernelObjects + <$(SOURCE_GRIST)>chmod.c + <$(SOURCE_GRIST)>stat.c + <$(SOURCE_GRIST)>mkdir.c + <$(SOURCE_GRIST)>sysctl.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/sys/chmod.c b/src/kernel/libroot/posix/sys/chmod.c new file mode 100644 index 0000000000..fc19e03c11 --- /dev/null +++ b/src/kernel/libroot/posix/sys/chmod.c @@ -0,0 +1,43 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +chmod(const char *path, mode_t mode) +{ + struct stat stat; + status_t status; + + stat.st_mode = mode; + status = sys_write_stat(-1, path, true, &stat, FS_WRITE_STAT_MODE); + + RETURN_AND_SET_ERRNO(status); +} + + +int +fchmod(int fd, mode_t mode) +{ + struct stat stat; + status_t status; + + stat.st_mode = mode; + status = sys_write_stat(fd, NULL, true, &stat, FS_WRITE_STAT_MODE); + + RETURN_AND_SET_ERRNO(status); +} diff --git a/src/kernel/libroot/posix/sys/mkdir.c b/src/kernel/libroot/posix/sys/mkdir.c new file mode 100644 index 0000000000..21939efcc2 --- /dev/null +++ b/src/kernel/libroot/posix/sys/mkdir.c @@ -0,0 +1,27 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +mkdir(const char *path, mode_t mode) +{ + status_t status = sys_create_dir(path, mode); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/sys/stat.c b/src/kernel/libroot/posix/sys/stat.c new file mode 100644 index 0000000000..1ecfc0b189 --- /dev/null +++ b/src/kernel/libroot/posix/sys/stat.c @@ -0,0 +1,44 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +stat(const char *path, struct stat *stat) +{ + int status = sys_read_stat(path, true, stat); + + RETURN_AND_SET_ERRNO(status); +} + + +int +lstat(const char *path, struct stat *stat) +{ + int status = sys_read_stat(path, false, stat); + + RETURN_AND_SET_ERRNO(status); +} + + +int +fstat(int fd, struct stat *stat) +{ + int status = sys_fstat(fd, stat); + + RETURN_AND_SET_ERRNO(status); +} diff --git a/src/kernel/libroot/posix/sys/sysctl.c b/src/kernel/libroot/posix/sys/sysctl.c new file mode 100644 index 0000000000..0843acbd72 --- /dev/null +++ b/src/kernel/libroot/posix/sys/sysctl.c @@ -0,0 +1,27 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +#include +#include +#include "syscalls.h" + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +sysctl(int *name, uint namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) +{ + /* ToDo: we should handle CTL_USER here, but as we don't even define it yet :) */ + int err = sys_sysctl(name, namelen, oldp, oldlenp, newp, newlen); + + RETURN_AND_SET_ERRNO(err) +} + diff --git a/src/kernel/libroot/posix/unistd/Jamfile b/src/kernel/libroot/posix/unistd/Jamfile new file mode 100644 index 0000000000..f6b1ca802b --- /dev/null +++ b/src/kernel/libroot/posix/unistd/Jamfile @@ -0,0 +1,24 @@ +SubDir OBOS_TOP src kernel libroot posix unistd ; + +KernelObjects + <$(SOURCE_GRIST)>access.c + <$(SOURCE_GRIST)>chown.c + <$(SOURCE_GRIST)>close.c + <$(SOURCE_GRIST)>dup.c + <$(SOURCE_GRIST)>dup2.c + <$(SOURCE_GRIST)>getopt.c + <$(SOURCE_GRIST)>lseek.c + <$(SOURCE_GRIST)>open.c + <$(SOURCE_GRIST)>directory.c + <$(SOURCE_GRIST)>link.c + <$(SOURCE_GRIST)>read.c + <$(SOURCE_GRIST)>sleep.c + <$(SOURCE_GRIST)>usleep.c + <$(SOURCE_GRIST)>truncate.c + <$(SOURCE_GRIST)>write.c + <$(SOURCE_GRIST)>ioctl.c + <$(SOURCE_GRIST)>mount.c + <$(SOURCE_GRIST)>conf.c + : + -fPIC -DPIC + ; diff --git a/src/kernel/libroot/posix/unistd/access.c b/src/kernel/libroot/posix/unistd/access.c new file mode 100644 index 0000000000..c03b041581 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/access.c @@ -0,0 +1,27 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +access(const char *path, int accessMode) +{ + status_t status = sys_access(path, accessMode); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/chown.c b/src/kernel/libroot/posix/unistd/chown.c new file mode 100644 index 0000000000..c23b273960 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/chown.c @@ -0,0 +1,60 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +chown(const char *path, uid_t owner, gid_t group) +{ + struct stat stat; + status_t status; + + stat.st_uid = owner; + stat.st_gid = group; + status = sys_write_stat(-1, path, true, &stat, FS_WRITE_STAT_UID | FS_WRITE_STAT_GID); + + RETURN_AND_SET_ERRNO(status); +} + + +int +lchown(const char *path, uid_t owner, gid_t group) +{ + struct stat stat; + status_t status; + + stat.st_uid = owner; + stat.st_gid = group; + status = sys_write_stat(-1, path, false, &stat, FS_WRITE_STAT_UID | FS_WRITE_STAT_GID); + + RETURN_AND_SET_ERRNO(status); +} + + +int +fchown(int fd, uid_t owner, gid_t group) +{ + struct stat stat; + status_t status; + + stat.st_uid = owner; + stat.st_gid = group; + status = sys_write_stat(fd, NULL, true, &stat, FS_WRITE_STAT_UID | FS_WRITE_STAT_GID); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/close.c b/src/kernel/libroot/posix/unistd/close.c new file mode 100644 index 0000000000..2ed3277022 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/close.c @@ -0,0 +1,20 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include +#include + +int close(int fd) +{ + int retval = sys_close(fd); + + if (retval < 0) { + errno = retval; + retval = -1; + } + + return retval; +} diff --git a/src/kernel/libroot/posix/unistd/conf.c b/src/kernel/libroot/posix/unistd/conf.c new file mode 100644 index 0000000000..69fddd2390 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/conf.c @@ -0,0 +1,46 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include +#include + + +int +getdtablesize(void) +{ + struct rlimit rlimit; + if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0) + return 0; + + return rlimit.rlim_cur; +} + + +long +sysconf(int name) +{ + // ToDo: implement sysconf() + return -1; +} + + +long +fpathconf(int fd, int name) +{ + // ToDo: implement fpathconf() + return -1; +} + + +long +pathconf(const char *path, int name) +{ + // ToDo: implement pathconf() + return -1; +} + diff --git a/src/kernel/libroot/posix/unistd/directory.c b/src/kernel/libroot/posix/unistd/directory.c new file mode 100644 index 0000000000..f6ed899b1b --- /dev/null +++ b/src/kernel/libroot/posix/unistd/directory.c @@ -0,0 +1,120 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define BUFFER_SIZE 4096 + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +DIR * +opendir(const char *path) +{ + DIR *dir; + + int fd = sys_open_dir(path); + if (fd < 0) + return NULL; + + /* allocate the memory for the DIR structure */ + if ((dir = (DIR*)malloc(sizeof(DIR) + BUFFER_SIZE)) == NULL) + return NULL; + + dir->fd = fd; + + return dir; +} + + +int +closedir(DIR *dir) +{ + int status = sys_close(dir->fd); + + free(dir); + + RETURN_AND_SET_ERRNO(status); +} + + +struct dirent * +readdir(DIR *dir) +{ + /* get the next entry and return a pointer to a dirent structure + * containing the data + */ + + ssize_t count = sys_read_dir(dir->fd, &dir->ent, BUFFER_SIZE, 1); + if (count <= 0) + return NULL; + + return &dir->ent; +} + + +void +rewinddir(DIR *dirp) +{ + status_t status; + + status = sys_rewind_dir(dirp->fd); + if (status < 0) + errno = status; +} + + +int +chdir(const char *path) +{ + int status = sys_setcwd(-1, path); + + RETURN_AND_SET_ERRNO(status); +} + + +int +fchdir(int fd) +{ + int status = sys_setcwd(fd, NULL); + + RETURN_AND_SET_ERRNO(status); +} + + +char * +getcwd(char *buffer, size_t size) +{ + int status = sys_getcwd(buffer, size); + if (status < B_OK) { + errno = status; + return NULL; + } + return buffer; +} + + +int +rmdir(const char *path) +{ + int status = sys_remove_dir(path); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/dup.c b/src/kernel/libroot/posix/unistd/dup.c new file mode 100644 index 0000000000..f2acdb85d0 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/dup.c @@ -0,0 +1,22 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +int +dup(int fd) +{ + int retval; + + retval= sys_dup(fd); + + if(retval< 0) { + // set errno + } + + return retval; +} diff --git a/src/kernel/libroot/posix/unistd/dup2.c b/src/kernel/libroot/posix/unistd/dup2.c new file mode 100644 index 0000000000..9779af686f --- /dev/null +++ b/src/kernel/libroot/posix/unistd/dup2.c @@ -0,0 +1,22 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +int +dup2(int ofd, int nfd) +{ + int retval; + + retval= sys_dup2(ofd, nfd); + + if(retval< 0) { + // set errno + } + + return retval; +} diff --git a/src/kernel/libroot/posix/unistd/getopt.c b/src/kernel/libroot/posix/unistd/getopt.c new file mode 100644 index 0000000000..7984053a97 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/getopt.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = 0; /* character checked for validity */ +int optreset = 0; /* reset getopt */ +char *optarg = NULL; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +getopt(nargc, nargv, ostr) + int nargc; + char * const *nargv; + const char *ostr; +{ + extern char *__progname; + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (optopt == (int)'-') + return (-1); + if (!*place) + ++optind; + if (opterr && *ostr != ':') + /* this should really be fprintf(stderr... */ + (void)printf("%s: illegal option -- %c\n", + __progname, optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + /* XXX - This is really fprintf(stderr... */ + (void)printf("%s: option requires an argument -- %c\n", + __progname, optopt); + return (BADCH); + } + else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +} diff --git a/src/kernel/libroot/posix/unistd/ioctl.c b/src/kernel/libroot/posix/unistd/ioctl.c new file mode 100644 index 0000000000..625de008a8 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/ioctl.c @@ -0,0 +1,34 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +ioctl(int fd, ulong cmd, ...) +{ + va_list args; + int err; + + va_start(args, cmd); + err = sys_ioctl(fd, cmd, args, IOCPARM_LEN(cmd)); + va_end(args); + + RETURN_AND_SET_ERRNO(err) +} + diff --git a/src/kernel/libroot/posix/unistd/link.c b/src/kernel/libroot/posix/unistd/link.c new file mode 100644 index 0000000000..851b0ab67e --- /dev/null +++ b/src/kernel/libroot/posix/unistd/link.c @@ -0,0 +1,54 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +ssize_t +readlink(const char *path, char *buffer, size_t bufferSize) +{ + int status = sys_read_link(path, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} + + +int +symlink(const char *path, const char *toPath) +{ + int status = sys_create_symlink(path, toPath, 0); + + RETURN_AND_SET_ERRNO(status); +} + + +int +unlink(const char *path) +{ + int status = sys_unlink(path); + + RETURN_AND_SET_ERRNO(status); +} + + +int +link(const char *path, const char *toPath) +{ + int status = sys_create_link(path, toPath); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/lseek.c b/src/kernel/libroot/posix/unistd/lseek.c new file mode 100644 index 0000000000..d991f48025 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/lseek.c @@ -0,0 +1,14 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +off_t +lseek(int fd, off_t pos, int whence) +{ + return sys_seek(fd, pos, whence); +} diff --git a/src/kernel/libroot/posix/unistd/mount.c b/src/kernel/libroot/posix/unistd/mount.c new file mode 100644 index 0000000000..d21b24bb15 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/mount.c @@ -0,0 +1,39 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +mount(const char *filesystem, const char *where, const char *device, ulong flags, void *parms, int len) +{ + // ToDo: consider parsing "parms" string in userland + int status = sys_mount(where, device, filesystem/*, flags*/, parms); + + (void)len; + + RETURN_AND_SET_ERRNO(status); +} + + +int +unmount(const char *path) +{ + int status = sys_unmount(path); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/open.c b/src/kernel/libroot/posix/unistd/open.c new file mode 100644 index 0000000000..6104b40743 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/open.c @@ -0,0 +1,48 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include +#include +#include + +#include + + +int +creat(const char *path, mode_t mode) +{ + int status = sys_create(path, O_CREAT | O_TRUNC | O_WRONLY, mode); + + if (status < 0) { + errno = status; + return -1; + } + return status; +} + + +int +open(const char *path, int oflags, ...) +{ + int status; + int perms; + va_list args; + + va_start(args, oflags); + perms = va_arg(args,int); + va_end(args); + + if (oflags & O_CREAT) + status = sys_create(path, oflags, perms); + else + status = sys_open(path, oflags); + + if (status < 0) { + errno = status; + return -1; + } + return status; +} diff --git a/src/kernel/libroot/posix/unistd/read.c b/src/kernel/libroot/posix/unistd/read.c new file mode 100644 index 0000000000..9596c5e718 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/read.c @@ -0,0 +1,50 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +ssize_t +read(int fd, void *buffer, size_t bufferSize) +{ + int status = sys_read(fd, -1, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} + + +ssize_t +read_pos(int fd, off_t pos, void *buffer, size_t bufferSize) +{ + int status = sys_read(fd, pos, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} + + +ssize_t +pread(int fd, void *buffer, size_t bufferSize, off_t pos) +{ + int status = sys_read(fd, pos, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/sleep.c b/src/kernel/libroot/posix/unistd/sleep.c new file mode 100644 index 0000000000..f2c7a60295 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/sleep.c @@ -0,0 +1,31 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +unsigned +sleep(unsigned seconds) +{ + bigtime_t usecs; + bigtime_t start; + int err; + unsigned retval; + + start= sys_system_time(); + + usecs= 1000000; + usecs*= (bigtime_t) seconds; + + err= sys_snooze(usecs); + + retval= 0; + if(err) { + retval= (unsigned)(sys_system_time()-start); + } + + return retval; +} diff --git a/src/kernel/libroot/posix/unistd/truncate.c b/src/kernel/libroot/posix/unistd/truncate.c new file mode 100644 index 0000000000..82c706178d --- /dev/null +++ b/src/kernel/libroot/posix/unistd/truncate.c @@ -0,0 +1,44 @@ +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +int +truncate(const char *path, off_t newSize) +{ + struct stat stat; + status_t status; + + stat.st_size = newSize; + status = sys_write_stat(-1, path, true, &stat, FS_WRITE_STAT_SIZE); + + RETURN_AND_SET_ERRNO(status); +} + + +int +ftruncate(int fd, off_t newSize) +{ + struct stat stat; + status_t status; + + stat.st_size = newSize; + status = sys_write_stat(fd, NULL, true, &stat, FS_WRITE_STAT_SIZE); + + RETURN_AND_SET_ERRNO(status); +} + diff --git a/src/kernel/libroot/posix/unistd/usleep.c b/src/kernel/libroot/posix/unistd/usleep.c new file mode 100644 index 0000000000..6a09a310c3 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/usleep.c @@ -0,0 +1,14 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +#include +#include + + +int +usleep(unsigned useconds) +{ + return sys_snooze((bigtime_t)(useconds)); +} diff --git a/src/kernel/libroot/posix/unistd/write.c b/src/kernel/libroot/posix/unistd/write.c new file mode 100644 index 0000000000..bb7606d220 --- /dev/null +++ b/src/kernel/libroot/posix/unistd/write.c @@ -0,0 +1,49 @@ +/* +** Copyright 2001, Manuel J. Petit. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + +/* +** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +#include +#include +#include + + +#define RETURN_AND_SET_ERRNO(err) \ + if (err < 0) { \ + errno = err; \ + return -1; \ + } \ + return err; + + +ssize_t +write(int fd, void const *buffer, size_t bufferSize) +{ + int status = sys_write(fd, -1, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} + + +ssize_t +write_pos(int fd, off_t pos, const void *buffer, size_t bufferSize) +{ + int status = sys_write(fd, pos, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} + + +ssize_t +pwrite(int fd, const void *buffer, size_t bufferSize, off_t pos) +{ + int status = sys_write(fd, pos, buffer, bufferSize); + + RETURN_AND_SET_ERRNO(status); +} +