initial check-in, version 0.5.0
authorRich Felker <dalias@aerifal.cx>
Sat, 12 Feb 2011 05:22:29 +0000 (00:22 -0500)
committerRich Felker <dalias@aerifal.cx>
Sat, 12 Feb 2011 05:22:29 +0000 (00:22 -0500)
1021 files changed:
COPYING [new file with mode: 0644]
COPYRIGHT [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
crt/crt1.c [new file with mode: 0644]
crt/crti.c [new file with mode: 0644]
crt/crtn.c [new file with mode: 0644]
crt/i386/crt1.s [new file with mode: 0644]
dist/config.mak [new file with mode: 0644]
include/alloca.h [new file with mode: 0644]
include/arpa/inet.h [new file with mode: 0644]
include/arpa/nameser.h [new file with mode: 0644]
include/arpa/telnet.h [new file with mode: 0644]
include/assert.h [new file with mode: 0644]
include/bits/alltypes.h.sh [new file with mode: 0755]
include/bits/endian.h [new file with mode: 0644]
include/bits/errno.h [new file with mode: 0644]
include/bits/fcntl.h [new file with mode: 0644]
include/bits/fenv.h [new file with mode: 0644]
include/bits/float.h [new file with mode: 0644]
include/bits/in.h [new file with mode: 0644]
include/bits/ioctl.h [new file with mode: 0644]
include/bits/ipc.h [new file with mode: 0644]
include/bits/limits.h [new file with mode: 0644]
include/bits/mman.h [new file with mode: 0644]
include/bits/posix.h [new file with mode: 0644]
include/bits/pthread.h [new file with mode: 0644]
include/bits/reg.h [new file with mode: 0644]
include/bits/setjmp.h [new file with mode: 0644]
include/bits/shm.h [new file with mode: 0644]
include/bits/signal.h [new file with mode: 0644]
include/bits/socket.h [new file with mode: 0644]
include/bits/stat.h [new file with mode: 0644]
include/bits/statfs.h [new file with mode: 0644]
include/bits/stdint.h [new file with mode: 0644]
include/bits/stdio.h [new file with mode: 0644]
include/bits/sysmacros.h [new file with mode: 0644]
include/bits/tcp.h [new file with mode: 0644]
include/bits/termios.h [new file with mode: 0644]
include/bits/uio.h [new file with mode: 0644]
include/bits/user.h [new file with mode: 0644]
include/bits/wait.h [new file with mode: 0644]
include/bits/wexitstatus.h [new file with mode: 0644]
include/byteswap.h [new file with mode: 0644]
include/cpio.h [new file with mode: 0644]
include/ctype.h [new file with mode: 0644]
include/dirent.h [new file with mode: 0644]
include/dlfcn.h [new file with mode: 0644]
include/elf.h [new file with mode: 0644]
include/endian.h [new file with mode: 0644]
include/errno.h [new file with mode: 0644]
include/fcntl.h [new file with mode: 0644]
include/features.h [new file with mode: 0644]
include/fenv.h [new file with mode: 0644]
include/float.h [new file with mode: 0644]
include/fnmatch.h [new file with mode: 0644]
include/ftw.h [new file with mode: 0644]
include/getopt.h [new file with mode: 0644]
include/glob.h [new file with mode: 0644]
include/grp.h [new file with mode: 0644]
include/iconv.h [new file with mode: 0644]
include/inttypes.h [new file with mode: 0644]
include/langinfo.h [new file with mode: 0644]
include/libgen.h [new file with mode: 0644]
include/libintl.h [new file with mode: 0644]
include/limits.h [new file with mode: 0644]
include/linux/loop.h [new file with mode: 0644]
include/linux/version.h [new file with mode: 0644]
include/locale.h [new file with mode: 0644]
include/malloc.h [new file with mode: 0644]
include/math.h [new file with mode: 0644]
include/mntent.h [new file with mode: 0644]
include/net/ethernet.h [new file with mode: 0644]
include/net/if.h [new file with mode: 0644]
include/net/if_arp.h [new file with mode: 0644]
include/net/route.h [new file with mode: 0644]
include/netdb.h [new file with mode: 0644]
include/netinet/icmp6.h [new file with mode: 0644]
include/netinet/if_ether.h [new file with mode: 0644]
include/netinet/in.h [new file with mode: 0644]
include/netinet/ip.h [new file with mode: 0644]
include/netinet/ip6.h [new file with mode: 0644]
include/netinet/ip_icmp.h [new file with mode: 0644]
include/netinet/tcp.h [new file with mode: 0644]
include/netinet/udp.h [new file with mode: 0644]
include/nl_types.h [new file with mode: 0644]
include/paths.h [new file with mode: 0644]
include/poll.h [new file with mode: 0644]
include/pthread.h [new file with mode: 0644]
include/pty.h [new file with mode: 0644]
include/pwd.h [new file with mode: 0644]
include/regex.h [new file with mode: 0644]
include/resolv.h [new file with mode: 0644]
include/sched.h [new file with mode: 0644]
include/search.h [new file with mode: 0644]
include/semaphore.h [new file with mode: 0644]
include/setjmp.h [new file with mode: 0644]
include/shadow.h [new file with mode: 0644]
include/signal.h [new file with mode: 0644]
include/stdarg.h [new file with mode: 0644]
include/stdbool.h [new file with mode: 0644]
include/stddef.h [new file with mode: 0644]
include/stdint.h [new file with mode: 0644]
include/stdio.h [new file with mode: 0644]
include/stdlib.h [new file with mode: 0644]
include/string.h [new file with mode: 0644]
include/strings.h [new file with mode: 0644]
include/stropts.h [new file with mode: 0644]
include/sys/epoll.h [new file with mode: 0644]
include/sys/file.h [new file with mode: 0644]
include/sys/ioctl.h [new file with mode: 0644]
include/sys/ipc.h [new file with mode: 0644]
include/sys/kd.h [new file with mode: 0644]
include/sys/klog.h [new file with mode: 0644]
include/sys/mman.h [new file with mode: 0644]
include/sys/mount.h [new file with mode: 0644]
include/sys/msg.h [new file with mode: 0644]
include/sys/param.h [new file with mode: 0644]
include/sys/poll.h [new file with mode: 0644]
include/sys/prctl.h [new file with mode: 0644]
include/sys/procfs.h [new file with mode: 0644]
include/sys/ptrace.h [new file with mode: 0644]
include/sys/reboot.h [new file with mode: 0644]
include/sys/reg.h [new file with mode: 0644]
include/sys/resource.h [new file with mode: 0644]
include/sys/select.h [new file with mode: 0644]
include/sys/sem.h [new file with mode: 0644]
include/sys/shm.h [new file with mode: 0644]
include/sys/signalfd.h [new file with mode: 0644]
include/sys/socket.h [new file with mode: 0644]
include/sys/soundcard.h [new file with mode: 0644]
include/sys/stat.h [new file with mode: 0644]
include/sys/statfs.h [new file with mode: 0644]
include/sys/statvfs.h [new file with mode: 0644]
include/sys/stropts.h [new file with mode: 0644]
include/sys/swap.h [new file with mode: 0644]
include/sys/sysctl.h [new file with mode: 0644]
include/sys/sysinfo.h [new file with mode: 0644]
include/sys/sysmacros.h [new file with mode: 0644]
include/sys/time.h [new file with mode: 0644]
include/sys/times.h [new file with mode: 0644]
include/sys/types.h [new file with mode: 0644]
include/sys/ucontext.h [new file with mode: 0644]
include/sys/uio.h [new file with mode: 0644]
include/sys/un.h [new file with mode: 0644]
include/sys/user.h [new file with mode: 0644]
include/sys/utsname.h [new file with mode: 0644]
include/sys/vfs.h [new file with mode: 0644]
include/sys/vt.h [new file with mode: 0644]
include/sys/wait.h [new file with mode: 0644]
include/syslog.h [new file with mode: 0644]
include/tar.h [new file with mode: 0644]
include/termios.h [new file with mode: 0644]
include/time.h [new file with mode: 0644]
include/ucontext.h [new file with mode: 0644]
include/ulimit.h [new file with mode: 0644]
include/unistd.h [new file with mode: 0644]
include/utime.h [new file with mode: 0644]
include/utmp.h [new file with mode: 0644]
include/utmpx.h [new file with mode: 0644]
include/wchar.h [new file with mode: 0644]
include/wctype.h [new file with mode: 0644]
include/wordexp.h [new file with mode: 0644]
src/conf/fpathconf.c [new file with mode: 0644]
src/conf/pathconf.c [new file with mode: 0644]
src/conf/sysconf.c [new file with mode: 0644]
src/ctype/__ctype_get_mb_cur_max.c [new file with mode: 0644]
src/ctype/isalnum.c [new file with mode: 0644]
src/ctype/isalpha.c [new file with mode: 0644]
src/ctype/isascii.c [new file with mode: 0644]
src/ctype/isblank.c [new file with mode: 0644]
src/ctype/iscntrl.c [new file with mode: 0644]
src/ctype/isdigit.c [new file with mode: 0644]
src/ctype/isgraph.c [new file with mode: 0644]
src/ctype/islower.c [new file with mode: 0644]
src/ctype/isprint.c [new file with mode: 0644]
src/ctype/ispunct.c [new file with mode: 0644]
src/ctype/isspace.c [new file with mode: 0644]
src/ctype/isupper.c [new file with mode: 0644]
src/ctype/iswalnum.c [new file with mode: 0644]
src/ctype/iswalpha.c [new file with mode: 0644]
src/ctype/iswblank.c [new file with mode: 0644]
src/ctype/iswcntrl.c [new file with mode: 0644]
src/ctype/iswctype.c [new file with mode: 0644]
src/ctype/iswdigit.c [new file with mode: 0644]
src/ctype/iswgraph.c [new file with mode: 0644]
src/ctype/iswlower.c [new file with mode: 0644]
src/ctype/iswprint.c [new file with mode: 0644]
src/ctype/iswpunct.c [new file with mode: 0644]
src/ctype/iswspace.c [new file with mode: 0644]
src/ctype/iswupper.c [new file with mode: 0644]
src/ctype/iswxdigit.c [new file with mode: 0644]
src/ctype/isxdigit.c [new file with mode: 0644]
src/ctype/toascii.c [new file with mode: 0644]
src/ctype/tolower.c [new file with mode: 0644]
src/ctype/toupper.c [new file with mode: 0644]
src/ctype/towctrans.c [new file with mode: 0644]
src/ctype/wcswidth.c [new file with mode: 0644]
src/ctype/wctrans.c [new file with mode: 0644]
src/ctype/wcwidth.c [new file with mode: 0644]
src/dirent/__dirent.h [new file with mode: 0644]
src/dirent/__getdents.c [new file with mode: 0644]
src/dirent/alphasort.c [new file with mode: 0644]
src/dirent/closedir.c [new file with mode: 0644]
src/dirent/dirfd.c [new file with mode: 0644]
src/dirent/fdopendir.c [new file with mode: 0644]
src/dirent/opendir.c [new file with mode: 0644]
src/dirent/readdir.c [new file with mode: 0644]
src/dirent/readdir_r.c [new file with mode: 0644]
src/dirent/rewinddir.c [new file with mode: 0644]
src/dirent/scandir.c [new file with mode: 0644]
src/dirent/seekdir.c [new file with mode: 0644]
src/dirent/telldir.c [new file with mode: 0644]
src/env/__environ.c [new file with mode: 0644]
src/env/__libc_start_main.c [new file with mode: 0644]
src/env/clearenv.c [new file with mode: 0644]
src/env/getenv.c [new file with mode: 0644]
src/env/putenv.c [new file with mode: 0644]
src/env/setenv.c [new file with mode: 0644]
src/env/unsetenv.c [new file with mode: 0644]
src/errno/__errno_location.c [new file with mode: 0644]
src/errno/__strerror.h [new file with mode: 0644]
src/errno/strerror.c [new file with mode: 0644]
src/exit/_Exit.c [new file with mode: 0644]
src/exit/abort.c [new file with mode: 0644]
src/exit/assert.c [new file with mode: 0644]
src/exit/atexit.c [new file with mode: 0644]
src/exit/exit.c [new file with mode: 0644]
src/fcntl/creat.c [new file with mode: 0644]
src/fcntl/fcntl.c [new file with mode: 0644]
src/fcntl/open.c [new file with mode: 0644]
src/fcntl/openat.c [new file with mode: 0644]
src/internal/atomic.h [new file with mode: 0644]
src/internal/clone.h [new file with mode: 0644]
src/internal/futex.h [new file with mode: 0644]
src/internal/libc.c [new file with mode: 0644]
src/internal/libc.h [new file with mode: 0644]
src/internal/locale_impl.h [new file with mode: 0644]
src/internal/pthread_impl.h [new file with mode: 0644]
src/internal/stdio_impl.h [new file with mode: 0644]
src/internal/syscall.c [new file with mode: 0644]
src/internal/syscall.h [new file with mode: 0644]
src/internal/util.h [new file with mode: 0644]
src/ipc/ftok.c [new file with mode: 0644]
src/ipc/ipc.h [new file with mode: 0644]
src/ipc/semctl.c [new file with mode: 0644]
src/ipc/semget.c [new file with mode: 0644]
src/ipc/semop.c [new file with mode: 0644]
src/ipc/shmat.c [new file with mode: 0644]
src/ipc/shmctl.c [new file with mode: 0644]
src/ipc/shmdt.c [new file with mode: 0644]
src/ipc/shmget.c [new file with mode: 0644]
src/linux/brk.c [new file with mode: 0644]
src/linux/chroot.c [new file with mode: 0644]
src/linux/daemon.c [new file with mode: 0644]
src/linux/epoll_create.c [new file with mode: 0644]
src/linux/epoll_create1.c [new file with mode: 0644]
src/linux/epoll_ctl.c [new file with mode: 0644]
src/linux/epoll_pwait.c [new file with mode: 0644]
src/linux/epoll_wait.c [new file with mode: 0644]
src/linux/getdtablesize.c [new file with mode: 0644]
src/linux/gethostid.c [new file with mode: 0644]
src/linux/getopt_long.c [new file with mode: 0644]
src/linux/getpagesize.c [new file with mode: 0644]
src/linux/getpass.c [new file with mode: 0644]
src/linux/initgroups.c [new file with mode: 0644]
src/linux/klogctl.c [new file with mode: 0644]
src/linux/mntent.c [new file with mode: 0644]
src/linux/mount.c [new file with mode: 0644]
src/linux/prctl.c [new file with mode: 0644]
src/linux/reboot.c [new file with mode: 0644]
src/linux/sbrk.c [new file with mode: 0644]
src/linux/sendfile.c [new file with mode: 0644]
src/linux/setgroups.c [new file with mode: 0644]
src/linux/sethostname.c [new file with mode: 0644]
src/linux/settimeofday.c [new file with mode: 0644]
src/linux/signalfd.c [new file with mode: 0644]
src/linux/stime.c [new file with mode: 0644]
src/linux/swapoff.c [new file with mode: 0644]
src/linux/swapon.c [new file with mode: 0644]
src/linux/sysinfo.c [new file with mode: 0644]
src/linux/umount.c [new file with mode: 0644]
src/linux/umount2.c [new file with mode: 0644]
src/linux/utimes.c [new file with mode: 0644]
src/linux/wait3.c [new file with mode: 0644]
src/linux/wait4.c [new file with mode: 0644]
src/locale/catclose.c [new file with mode: 0644]
src/locale/catgets.c [new file with mode: 0644]
src/locale/catopen.c [new file with mode: 0644]
src/locale/duplocale.c [new file with mode: 0644]
src/locale/freelocale.c [new file with mode: 0644]
src/locale/iconv.c [new file with mode: 0644]
src/locale/intl.c [new file with mode: 0644]
src/locale/isalnum_l.c [new file with mode: 0644]
src/locale/isalpha_l.c [new file with mode: 0644]
src/locale/isblank_l.c [new file with mode: 0644]
src/locale/iscntrl_l.c [new file with mode: 0644]
src/locale/isdigit_l.c [new file with mode: 0644]
src/locale/isgraph_l.c [new file with mode: 0644]
src/locale/islower_l.c [new file with mode: 0644]
src/locale/isprint_l.c [new file with mode: 0644]
src/locale/ispunct_l.c [new file with mode: 0644]
src/locale/isspace_l.c [new file with mode: 0644]
src/locale/isupper_l.c [new file with mode: 0644]
src/locale/isxdigit_l.c [new file with mode: 0644]
src/locale/langinfo.c [new file with mode: 0644]
src/locale/localeconv.c [new file with mode: 0644]
src/locale/newlocale.c [new file with mode: 0644]
src/locale/nl_langinfo.c [new file with mode: 0644]
src/locale/setlocale.c [new file with mode: 0644]
src/locale/strcoll.c [new file with mode: 0644]
src/locale/strxfrm.c [new file with mode: 0644]
src/locale/tmp [new file with mode: 0644]
src/locale/tolower_l.c [new file with mode: 0644]
src/locale/toupper_l.c [new file with mode: 0644]
src/locale/wcscoll.c [new file with mode: 0644]
src/locale/wcsxfrm.c [new file with mode: 0644]
src/malloc/DESIGN [new file with mode: 0644]
src/malloc/__brk.c [new file with mode: 0644]
src/malloc/__simple_malloc.c [new file with mode: 0644]
src/malloc/calloc.c [new file with mode: 0644]
src/malloc/malloc.c [new file with mode: 0644]
src/malloc/memalign.c [new file with mode: 0644]
src/malloc/posix_memalign.c [new file with mode: 0644]
src/math/__fpclassify.c [new file with mode: 0644]
src/math/__fpclassifyf.c [new file with mode: 0644]
src/math/__fpclassifyl.c [new file with mode: 0644]
src/math/e_acos.c [new file with mode: 0644]
src/math/e_acosf.c [new file with mode: 0644]
src/math/e_acosh.c [new file with mode: 0644]
src/math/e_acoshf.c [new file with mode: 0644]
src/math/e_asin.c [new file with mode: 0644]
src/math/e_asinf.c [new file with mode: 0644]
src/math/e_atan2.c [new file with mode: 0644]
src/math/e_atan2f.c [new file with mode: 0644]
src/math/e_atanh.c [new file with mode: 0644]
src/math/e_atanhf.c [new file with mode: 0644]
src/math/e_cosh.c [new file with mode: 0644]
src/math/e_coshf.c [new file with mode: 0644]
src/math/e_exp.c [new file with mode: 0644]
src/math/e_expf.c [new file with mode: 0644]
src/math/e_fmod.c [new file with mode: 0644]
src/math/e_fmodf.c [new file with mode: 0644]
src/math/e_hypot.c [new file with mode: 0644]
src/math/e_hypotf.c [new file with mode: 0644]
src/math/e_log.c [new file with mode: 0644]
src/math/e_log10.c [new file with mode: 0644]
src/math/e_log10f.c [new file with mode: 0644]
src/math/e_logf.c [new file with mode: 0644]
src/math/e_pow.c [new file with mode: 0644]
src/math/e_powf.c [new file with mode: 0644]
src/math/e_rem_pio2.c [new file with mode: 0644]
src/math/e_rem_pio2f.c [new file with mode: 0644]
src/math/e_remainder.c [new file with mode: 0644]
src/math/e_remainderf.c [new file with mode: 0644]
src/math/e_scalb.c [new file with mode: 0644]
src/math/e_scalbf.c [new file with mode: 0644]
src/math/e_sinh.c [new file with mode: 0644]
src/math/e_sinhf.c [new file with mode: 0644]
src/math/e_sqrt.c [new file with mode: 0644]
src/math/e_sqrtf.c [new file with mode: 0644]
src/math/i386/e_exp.s [new file with mode: 0644]
src/math/i386/e_expf.s [new file with mode: 0644]
src/math/i386/e_log.s [new file with mode: 0644]
src/math/i386/e_log10.s [new file with mode: 0644]
src/math/i386/e_log10f.s [new file with mode: 0644]
src/math/i386/e_logf.s [new file with mode: 0644]
src/math/i386/e_remainder.s [new file with mode: 0644]
src/math/i386/e_remainderf.s [new file with mode: 0644]
src/math/i386/e_sqrt.s [new file with mode: 0644]
src/math/i386/e_sqrtf.s [new file with mode: 0644]
src/math/i386/s_ceil.s [new file with mode: 0644]
src/math/i386/s_ceilf.s [new file with mode: 0644]
src/math/i386/s_fabs.s [new file with mode: 0644]
src/math/i386/s_fabsf.s [new file with mode: 0644]
src/math/i386/s_floor.s [new file with mode: 0644]
src/math/i386/s_floorf.s [new file with mode: 0644]
src/math/i386/s_ldexp.s [new file with mode: 0644]
src/math/i386/s_ldexpf.s [new file with mode: 0644]
src/math/i386/s_rint.s [new file with mode: 0644]
src/math/i386/s_rintf.s [new file with mode: 0644]
src/math/i386/s_scalbln.s [new file with mode: 0644]
src/math/i386/s_scalblnf.s [new file with mode: 0644]
src/math/i386/s_trunc.s [new file with mode: 0644]
src/math/i386/s_truncf.s [new file with mode: 0644]
src/math/k_cos.c [new file with mode: 0644]
src/math/k_cosf.c [new file with mode: 0644]
src/math/k_rem_pio2.c [new file with mode: 0644]
src/math/k_rem_pio2f.c [new file with mode: 0644]
src/math/k_sin.c [new file with mode: 0644]
src/math/k_sinf.c [new file with mode: 0644]
src/math/k_tan.c [new file with mode: 0644]
src/math/k_tanf.c [new file with mode: 0644]
src/math/math_private.h [new file with mode: 0644]
src/math/s_asinh.c [new file with mode: 0644]
src/math/s_asinhf.c [new file with mode: 0644]
src/math/s_atan.c [new file with mode: 0644]
src/math/s_atanf.c [new file with mode: 0644]
src/math/s_cbrt.c [new file with mode: 0644]
src/math/s_cbrtf.c [new file with mode: 0644]
src/math/s_ceil.c [new file with mode: 0644]
src/math/s_ceilf.c [new file with mode: 0644]
src/math/s_copysign.c [new file with mode: 0644]
src/math/s_copysignf.c [new file with mode: 0644]
src/math/s_cos.c [new file with mode: 0644]
src/math/s_cosf.c [new file with mode: 0644]
src/math/s_erf.c [new file with mode: 0644]
src/math/s_erff.c [new file with mode: 0644]
src/math/s_expm1.c [new file with mode: 0644]
src/math/s_expm1f.c [new file with mode: 0644]
src/math/s_fabs.c [new file with mode: 0644]
src/math/s_fabsf.c [new file with mode: 0644]
src/math/s_floor.c [new file with mode: 0644]
src/math/s_floorf.c [new file with mode: 0644]
src/math/s_ilogb.c [new file with mode: 0644]
src/math/s_ilogbf.c [new file with mode: 0644]
src/math/s_ldexp.c [new file with mode: 0644]
src/math/s_ldexpf.c [new file with mode: 0644]
src/math/s_llrint.c [new file with mode: 0644]
src/math/s_log1p.c [new file with mode: 0644]
src/math/s_log1pf.c [new file with mode: 0644]
src/math/s_logb.c [new file with mode: 0644]
src/math/s_logbf.c [new file with mode: 0644]
src/math/s_lrint.c [new file with mode: 0644]
src/math/s_lrintf.c [new file with mode: 0644]
src/math/s_modf.c [new file with mode: 0644]
src/math/s_modff.c [new file with mode: 0644]
src/math/s_nextafter.c [new file with mode: 0644]
src/math/s_nextafterf.c [new file with mode: 0644]
src/math/s_remquo.c [new file with mode: 0644]
src/math/s_remquof.c [new file with mode: 0644]
src/math/s_rint.c [new file with mode: 0644]
src/math/s_rintf.c [new file with mode: 0644]
src/math/s_round.c [new file with mode: 0644]
src/math/s_roundf.c [new file with mode: 0644]
src/math/s_scalbln.c [new file with mode: 0644]
src/math/s_scalblnf.c [new file with mode: 0644]
src/math/s_sin.c [new file with mode: 0644]
src/math/s_sinf.c [new file with mode: 0644]
src/math/s_tan.c [new file with mode: 0644]
src/math/s_tanf.c [new file with mode: 0644]
src/math/s_tanh.c [new file with mode: 0644]
src/math/s_tanhf.c [new file with mode: 0644]
src/math/s_trunc.c [new file with mode: 0644]
src/math/s_truncf.c [new file with mode: 0644]
src/misc/basename.c [new file with mode: 0644]
src/misc/bswap_32.c [new file with mode: 0644]
src/misc/bswap_64.c [new file with mode: 0644]
src/misc/crypt.c [new file with mode: 0644]
src/misc/cuserid.c [new file with mode: 0644]
src/misc/dirname.c [new file with mode: 0644]
src/misc/ffs.c [new file with mode: 0644]
src/misc/ftw.c [new file with mode: 0644]
src/misc/getdomainname.c [new file with mode: 0644]
src/misc/getgrouplist.c [new file with mode: 0644]
src/misc/getopt.c [new file with mode: 0644]
src/misc/getpriority.c [new file with mode: 0644]
src/misc/getrlimit.c [new file with mode: 0644]
src/misc/getrusage.c [new file with mode: 0644]
src/misc/getsubopt.c [new file with mode: 0644]
src/misc/ioctl.c [new file with mode: 0644]
src/misc/lockf.c [new file with mode: 0644]
src/misc/nftw.c [new file with mode: 0644]
src/misc/openpty.c [new file with mode: 0644]
src/misc/pty.c [new file with mode: 0644]
src/misc/realpath.c [new file with mode: 0644]
src/misc/sched_yield.c [new file with mode: 0644]
src/misc/setpriority.c [new file with mode: 0644]
src/misc/setrlimit.c [new file with mode: 0644]
src/misc/syslog.c [new file with mode: 0644]
src/misc/uname.c [new file with mode: 0644]
src/mman/madvise.c [new file with mode: 0644]
src/mman/mlock.c [new file with mode: 0644]
src/mman/mlockall.c [new file with mode: 0644]
src/mman/mmap.c [new file with mode: 0644]
src/mman/mprotect.c [new file with mode: 0644]
src/mman/mremap.c [new file with mode: 0644]
src/mman/msync.c [new file with mode: 0644]
src/mman/munlock.c [new file with mode: 0644]
src/mman/munlockall.c [new file with mode: 0644]
src/mman/munmap.c [new file with mode: 0644]
src/mman/posix_madvise.c [new file with mode: 0644]
src/multibyte/btowc.c [new file with mode: 0644]
src/multibyte/decode.c [new file with mode: 0644]
src/multibyte/internal.c [new file with mode: 0644]
src/multibyte/internal.h [new file with mode: 0644]
src/multibyte/mblen.c [new file with mode: 0644]
src/multibyte/mbrlen.c [new file with mode: 0644]
src/multibyte/mbrtowc.c [new file with mode: 0644]
src/multibyte/mbsinit.c [new file with mode: 0644]
src/multibyte/mbsnrtowcs.c [new file with mode: 0644]
src/multibyte/mbsrtowcs.c [new file with mode: 0644]
src/multibyte/mbstowcs.c [new file with mode: 0644]
src/multibyte/mbtowc.c [new file with mode: 0644]
src/multibyte/wcrtomb.c [new file with mode: 0644]
src/multibyte/wcsnrtombs.c [new file with mode: 0644]
src/multibyte/wcsrtombs.c [new file with mode: 0644]
src/multibyte/wcstombs.c [new file with mode: 0644]
src/multibyte/wctob.c [new file with mode: 0644]
src/multibyte/wctomb.c [new file with mode: 0644]
src/network/__dns.c [new file with mode: 0644]
src/network/__dns.h [new file with mode: 0644]
src/network/__ipparse.c [new file with mode: 0644]
src/network/accept.c [new file with mode: 0644]
src/network/bind.c [new file with mode: 0644]
src/network/connect.c [new file with mode: 0644]
src/network/dn_expand.c [new file with mode: 0644]
src/network/ent.c [new file with mode: 0644]
src/network/freeaddrinfo.c [new file with mode: 0644]
src/network/gai_strerror.c [new file with mode: 0644]
src/network/getaddrinfo.c [new file with mode: 0644]
src/network/gethostbyaddr.c [new file with mode: 0644]
src/network/gethostbyaddr_r.c [new file with mode: 0644]
src/network/gethostbyname.c [new file with mode: 0644]
src/network/gethostbyname2.c [new file with mode: 0644]
src/network/gethostbyname2_r.c [new file with mode: 0644]
src/network/gethostbyname_r.c [new file with mode: 0644]
src/network/getnameinfo.c [new file with mode: 0644]
src/network/getpeername.c [new file with mode: 0644]
src/network/getservbyname.c [new file with mode: 0644]
src/network/getservbyname_r.c [new file with mode: 0644]
src/network/getservbyport.c [new file with mode: 0644]
src/network/getservbyport_r.c [new file with mode: 0644]
src/network/getsockname.c [new file with mode: 0644]
src/network/getsockopt.c [new file with mode: 0644]
src/network/h_errno.c [new file with mode: 0644]
src/network/hstrerror.c [new file with mode: 0644]
src/network/htonl.c [new file with mode: 0644]
src/network/htons.c [new file with mode: 0644]
src/network/in6addr_any.c [new file with mode: 0644]
src/network/in6addr_loopback.c [new file with mode: 0644]
src/network/inet_addr.c [new file with mode: 0644]
src/network/inet_aton.c [new file with mode: 0644]
src/network/inet_ntoa.c [new file with mode: 0644]
src/network/inet_ntop.c [new file with mode: 0644]
src/network/inet_pton.c [new file with mode: 0644]
src/network/listen.c [new file with mode: 0644]
src/network/ntohl.c [new file with mode: 0644]
src/network/ntohs.c [new file with mode: 0644]
src/network/proto.c [new file with mode: 0644]
src/network/recv.c [new file with mode: 0644]
src/network/recvfrom.c [new file with mode: 0644]
src/network/recvmsg.c [new file with mode: 0644]
src/network/res_init.c [new file with mode: 0644]
src/network/res_query.c [new file with mode: 0644]
src/network/send.c [new file with mode: 0644]
src/network/sendmsg.c [new file with mode: 0644]
src/network/sendto.c [new file with mode: 0644]
src/network/serv.c [new file with mode: 0644]
src/network/setsockopt.c [new file with mode: 0644]
src/network/shutdown.c [new file with mode: 0644]
src/network/sockatmark.c [new file with mode: 0644]
src/network/socket.c [new file with mode: 0644]
src/network/socketcall.h [new file with mode: 0644]
src/network/socketpair.c [new file with mode: 0644]
src/passwd/getgr_r.c [new file with mode: 0644]
src/passwd/getgrent.c [new file with mode: 0644]
src/passwd/getgrent_a.c [new file with mode: 0644]
src/passwd/getpw_r.c [new file with mode: 0644]
src/passwd/getpwent.c [new file with mode: 0644]
src/passwd/getpwent_a.c [new file with mode: 0644]
src/passwd/getspent.c [new file with mode: 0644]
src/passwd/getspnam.c [new file with mode: 0644]
src/passwd/getspnam_r.c [new file with mode: 0644]
src/passwd/lckpwdf.c [new file with mode: 0644]
src/passwd/pwf.h [new file with mode: 0644]
src/prng/__rand48_step.c [new file with mode: 0644]
src/prng/__seed48.c [new file with mode: 0644]
src/prng/drand48.c [new file with mode: 0644]
src/prng/lcong48.c [new file with mode: 0644]
src/prng/lrand48.c [new file with mode: 0644]
src/prng/mrand48.c [new file with mode: 0644]
src/prng/rand.c [new file with mode: 0644]
src/prng/rand_r.c [new file with mode: 0644]
src/prng/random.c [new file with mode: 0644]
src/prng/seed48.c [new file with mode: 0644]
src/prng/srand48.c [new file with mode: 0644]
src/prng/srandom.c [new file with mode: 0644]
src/process/execl.c [new file with mode: 0644]
src/process/execle.c [new file with mode: 0644]
src/process/execlp.c [new file with mode: 0644]
src/process/execv.c [new file with mode: 0644]
src/process/execve.c [new file with mode: 0644]
src/process/execvp.c [new file with mode: 0644]
src/process/fork.c [new file with mode: 0644]
src/process/system.c [new file with mode: 0644]
src/process/vfork.c [new file with mode: 0644]
src/process/wait.c [new file with mode: 0644]
src/process/waitid.c [new file with mode: 0644]
src/process/waitpid.c [new file with mode: 0644]
src/regex/fnmatch.c [new file with mode: 0644]
src/regex/glob.c [new file with mode: 0644]
src/regex/regcomp.c [new file with mode: 0644]
src/regex/regerror.c [new file with mode: 0644]
src/regex/regexec.c [new file with mode: 0644]
src/regex/tre-mem.c [new file with mode: 0644]
src/regex/tre.h [new file with mode: 0644]
src/select/poll.c [new file with mode: 0644]
src/select/pselect.c [new file with mode: 0644]
src/select/select.c [new file with mode: 0644]
src/setjmp/i386/longjmp.s [new file with mode: 0644]
src/setjmp/i386/setjmp.s [new file with mode: 0644]
src/setjmp/longjmp.c [new file with mode: 0644]
src/setjmp/setjmp.c [new file with mode: 0644]
src/signal/bsd_signal.c [new file with mode: 0644]
src/signal/getitimer.c [new file with mode: 0644]
src/signal/i386/sigsetjmp.s [new file with mode: 0644]
src/signal/kill.c [new file with mode: 0644]
src/signal/killpg.c [new file with mode: 0644]
src/signal/raise.c [new file with mode: 0644]
src/signal/setitimer.c [new file with mode: 0644]
src/signal/sigaction.c [new file with mode: 0644]
src/signal/sigaddset.c [new file with mode: 0644]
src/signal/sigaltstack.c [new file with mode: 0644]
src/signal/sigdelset.c [new file with mode: 0644]
src/signal/sigemptyset.c [new file with mode: 0644]
src/signal/sigfillset.c [new file with mode: 0644]
src/signal/sighold.c [new file with mode: 0644]
src/signal/sigignore.c [new file with mode: 0644]
src/signal/siginterrupt.c [new file with mode: 0644]
src/signal/sigismember.c [new file with mode: 0644]
src/signal/siglongjmp.c [new file with mode: 0644]
src/signal/signal.c [new file with mode: 0644]
src/signal/sigpause.c [new file with mode: 0644]
src/signal/sigpending.c [new file with mode: 0644]
src/signal/sigprocmask.c [new file with mode: 0644]
src/signal/sigqueue.c [new file with mode: 0644]
src/signal/sigrelse.c [new file with mode: 0644]
src/signal/sigrtmax.c [new file with mode: 0644]
src/signal/sigrtmin.c [new file with mode: 0644]
src/signal/sigset.c [new file with mode: 0644]
src/signal/sigsetjmp.c [new file with mode: 0644]
src/signal/sigsuspend.c [new file with mode: 0644]
src/signal/sigtimedwait.c [new file with mode: 0644]
src/signal/sigwait.c [new file with mode: 0644]
src/signal/sigwaitinfo.c [new file with mode: 0644]
src/stat/chmod.c [new file with mode: 0644]
src/stat/fchmod.c [new file with mode: 0644]
src/stat/fchmodat.c [new file with mode: 0644]
src/stat/fstat.c [new file with mode: 0644]
src/stat/fstatat.c [new file with mode: 0644]
src/stat/fstatvfs.c [new file with mode: 0644]
src/stat/lstat.c [new file with mode: 0644]
src/stat/mkdir.c [new file with mode: 0644]
src/stat/mkdirat.c [new file with mode: 0644]
src/stat/mkfifo.c [new file with mode: 0644]
src/stat/mkfifoat.c [new file with mode: 0644]
src/stat/mknod.c [new file with mode: 0644]
src/stat/mknodat.c [new file with mode: 0644]
src/stat/stat.c [new file with mode: 0644]
src/stat/statvfs.c [new file with mode: 0644]
src/stat/umask.c [new file with mode: 0644]
src/stdio/__fclose_ca.c [new file with mode: 0644]
src/stdio/__fdopen.c [new file with mode: 0644]
src/stdio/__fopen_rb_ca.c [new file with mode: 0644]
src/stdio/__fpending.c [new file with mode: 0644]
src/stdio/__ofl.c [new file with mode: 0644]
src/stdio/__overflow.c [new file with mode: 0644]
src/stdio/__scanf.c [new file with mode: 0644]
src/stdio/__scanf.h [new file with mode: 0644]
src/stdio/__stdio_close.c [new file with mode: 0644]
src/stdio/__stdio_read.c [new file with mode: 0644]
src/stdio/__stdio_seek.c [new file with mode: 0644]
src/stdio/__stdio_write.c [new file with mode: 0644]
src/stdio/__uflow.c [new file with mode: 0644]
src/stdio/__underflow.c [new file with mode: 0644]
src/stdio/asprintf.c [new file with mode: 0644]
src/stdio/clearerr.c [new file with mode: 0644]
src/stdio/dprintf.c [new file with mode: 0644]
src/stdio/fclose.c [new file with mode: 0644]
src/stdio/feof.c [new file with mode: 0644]
src/stdio/ferror.c [new file with mode: 0644]
src/stdio/fflush.c [new file with mode: 0644]
src/stdio/fgetc.c [new file with mode: 0644]
src/stdio/fgetpos.c [new file with mode: 0644]
src/stdio/fgets.c [new file with mode: 0644]
src/stdio/fgetwc.c [new file with mode: 0644]
src/stdio/fgetws.c [new file with mode: 0644]
src/stdio/fileno.c [new file with mode: 0644]
src/stdio/fmemopen.c [new file with mode: 0644]
src/stdio/fopen.c [new file with mode: 0644]
src/stdio/fprintf.c [new file with mode: 0644]
src/stdio/fputc.c [new file with mode: 0644]
src/stdio/fputs.c [new file with mode: 0644]
src/stdio/fputwc.c [new file with mode: 0644]
src/stdio/fputws.c [new file with mode: 0644]
src/stdio/fread.c [new file with mode: 0644]
src/stdio/freopen.c [new file with mode: 0644]
src/stdio/fscanf.c [new file with mode: 0644]
src/stdio/fseek.c [new file with mode: 0644]
src/stdio/fsetpos.c [new file with mode: 0644]
src/stdio/ftell.c [new file with mode: 0644]
src/stdio/fwide.c [new file with mode: 0644]
src/stdio/fwrite.c [new file with mode: 0644]
src/stdio/fwscanf.c [new file with mode: 0644]
src/stdio/getc.c [new file with mode: 0644]
src/stdio/getc_unlocked.c [new file with mode: 0644]
src/stdio/getchar.c [new file with mode: 0644]
src/stdio/getchar_unlocked.c [new file with mode: 0644]
src/stdio/getdelim.c [new file with mode: 0644]
src/stdio/getline.c [new file with mode: 0644]
src/stdio/gets.c [new file with mode: 0644]
src/stdio/getw.c [new file with mode: 0644]
src/stdio/getwc.c [new file with mode: 0644]
src/stdio/getwchar.c [new file with mode: 0644]
src/stdio/pclose.c [new file with mode: 0644]
src/stdio/perror.c [new file with mode: 0644]
src/stdio/popen.c [new file with mode: 0644]
src/stdio/printf.c [new file with mode: 0644]
src/stdio/putc.c [new file with mode: 0644]
src/stdio/putc_unlocked.c [new file with mode: 0644]
src/stdio/putchar.c [new file with mode: 0644]
src/stdio/putchar_unlocked.c [new file with mode: 0644]
src/stdio/puts.c [new file with mode: 0644]
src/stdio/putw.c [new file with mode: 0644]
src/stdio/putwc.c [new file with mode: 0644]
src/stdio/putwchar.c [new file with mode: 0644]
src/stdio/remove.c [new file with mode: 0644]
src/stdio/rename.c [new file with mode: 0644]
src/stdio/rewind.c [new file with mode: 0644]
src/stdio/scanf.c [new file with mode: 0644]
src/stdio/setbuf.c [new file with mode: 0644]
src/stdio/setvbuf.c [new file with mode: 0644]
src/stdio/snprintf.c [new file with mode: 0644]
src/stdio/sprintf.c [new file with mode: 0644]
src/stdio/sscanf.c [new file with mode: 0644]
src/stdio/stderr.c [new file with mode: 0644]
src/stdio/stdin.c [new file with mode: 0644]
src/stdio/stdout.c [new file with mode: 0644]
src/stdio/swscanf.c [new file with mode: 0644]
src/stdio/tempnam.c [new file with mode: 0644]
src/stdio/tmpfile.c [new file with mode: 0644]
src/stdio/tmpnam.c [new file with mode: 0644]
src/stdio/ungetc.c [new file with mode: 0644]
src/stdio/ungetwc.c [new file with mode: 0644]
src/stdio/vasprintf.c [new file with mode: 0644]
src/stdio/vdprintf.c [new file with mode: 0644]
src/stdio/vfprintf.c [new file with mode: 0644]
src/stdio/vfscanf.c [new file with mode: 0644]
src/stdio/vfwscanf.c [new file with mode: 0644]
src/stdio/vprintf.c [new file with mode: 0644]
src/stdio/vscanf.c [new file with mode: 0644]
src/stdio/vsnprintf.c [new file with mode: 0644]
src/stdio/vsprintf.c [new file with mode: 0644]
src/stdio/vsscanf.c [new file with mode: 0644]
src/stdio/vswscanf.c [new file with mode: 0644]
src/stdio/vwscanf.c [new file with mode: 0644]
src/stdio/wscanf.c [new file with mode: 0644]
src/stdlib/abs.c [new file with mode: 0644]
src/stdlib/atof.c [new file with mode: 0644]
src/stdlib/atoi.c [new file with mode: 0644]
src/stdlib/atol.c [new file with mode: 0644]
src/stdlib/atoll.c [new file with mode: 0644]
src/stdlib/bsearch.c [new file with mode: 0644]
src/stdlib/div.c [new file with mode: 0644]
src/stdlib/frexp.c [new file with mode: 0644]
src/stdlib/frexpf.c [new file with mode: 0644]
src/stdlib/frexpl.c [new file with mode: 0644]
src/stdlib/imaxabs.c [new file with mode: 0644]
src/stdlib/imaxdiv.c [new file with mode: 0644]
src/stdlib/labs.c [new file with mode: 0644]
src/stdlib/ldiv.c [new file with mode: 0644]
src/stdlib/llabs.c [new file with mode: 0644]
src/stdlib/lldiv.c [new file with mode: 0644]
src/stdlib/qsort.c [new file with mode: 0644]
src/stdlib/strtod.c [new file with mode: 0644]
src/stdlib/strtof.c [new file with mode: 0644]
src/stdlib/strtoimax.c [new file with mode: 0644]
src/stdlib/strtol.c [new file with mode: 0644]
src/stdlib/strtold.c [new file with mode: 0644]
src/stdlib/strtoll.c [new file with mode: 0644]
src/stdlib/strtoul.c [new file with mode: 0644]
src/stdlib/strtoull.c [new file with mode: 0644]
src/stdlib/strtoumax.c [new file with mode: 0644]
src/stdlib/wcstoimax.c [new file with mode: 0644]
src/stdlib/wcstol.c [new file with mode: 0644]
src/stdlib/wcstoll.c [new file with mode: 0644]
src/stdlib/wcstoul.c [new file with mode: 0644]
src/stdlib/wcstoull.c [new file with mode: 0644]
src/stdlib/wcstoumax.c [new file with mode: 0644]
src/string/bcmp.c [new file with mode: 0644]
src/string/bcopy.c [new file with mode: 0644]
src/string/bzero.c [new file with mode: 0644]
src/string/index.c [new file with mode: 0644]
src/string/memchr.c [new file with mode: 0644]
src/string/memcmp.c [new file with mode: 0644]
src/string/memcpy.c [new file with mode: 0644]
src/string/memmove.c [new file with mode: 0644]
src/string/mempcpy.c [new file with mode: 0644]
src/string/memset.c [new file with mode: 0644]
src/string/rindex.c [new file with mode: 0644]
src/string/stpcpy.c [new file with mode: 0644]
src/string/stpncpy.c [new file with mode: 0644]
src/string/strcasecmp.c [new file with mode: 0644]
src/string/strcasestr.c [new file with mode: 0644]
src/string/strcat.c [new file with mode: 0644]
src/string/strchr.c [new file with mode: 0644]
src/string/strchrnul.c [new file with mode: 0644]
src/string/strcmp.c [new file with mode: 0644]
src/string/strcpy.c [new file with mode: 0644]
src/string/strcspn.c [new file with mode: 0644]
src/string/strdup.c [new file with mode: 0644]
src/string/strerror_r.c [new file with mode: 0644]
src/string/strlcat.c [new file with mode: 0644]
src/string/strlcpy.c [new file with mode: 0644]
src/string/strlen.c [new file with mode: 0644]
src/string/strncasecmp.c [new file with mode: 0644]
src/string/strncat.c [new file with mode: 0644]
src/string/strncmp.c [new file with mode: 0644]
src/string/strncpy.c [new file with mode: 0644]
src/string/strndup.c [new file with mode: 0644]
src/string/strnlen.c [new file with mode: 0644]
src/string/strpbrk.c [new file with mode: 0644]
src/string/strrchr.c [new file with mode: 0644]
src/string/strsep.c [new file with mode: 0644]
src/string/strsignal.c [new file with mode: 0644]
src/string/strspn.c [new file with mode: 0644]
src/string/strstr.c [new file with mode: 0644]
src/string/strtok.c [new file with mode: 0644]
src/string/strtok_r.c [new file with mode: 0644]
src/string/swab.c [new file with mode: 0644]
src/string/wcscat.c [new file with mode: 0644]
src/string/wcschr.c [new file with mode: 0644]
src/string/wcscmp.c [new file with mode: 0644]
src/string/wcscpy.c [new file with mode: 0644]
src/string/wcscspn.c [new file with mode: 0644]
src/string/wcslen.c [new file with mode: 0644]
src/string/wcsncat.c [new file with mode: 0644]
src/string/wcsncmp.c [new file with mode: 0644]
src/string/wcsncpy.c [new file with mode: 0644]
src/string/wcspbrk.c [new file with mode: 0644]
src/string/wcsrchr.c [new file with mode: 0644]
src/string/wcsspn.c [new file with mode: 0644]
src/string/wcsstr.c [new file with mode: 0644]
src/string/wcswcs.c [new file with mode: 0644]
src/string/wmemchr.c [new file with mode: 0644]
src/string/wmemcmp.c [new file with mode: 0644]
src/string/wmemcpy.c [new file with mode: 0644]
src/string/wmemmove.c [new file with mode: 0644]
src/string/wmemset.c [new file with mode: 0644]
src/stub/utmpx.c [new file with mode: 0644]
src/temp/mkdtemp.c [new file with mode: 0644]
src/temp/mkstemp.c [new file with mode: 0644]
src/temp/mktemp.c [new file with mode: 0644]
src/termios/cfgetospeed.c [new file with mode: 0644]
src/termios/cfsetospeed.c [new file with mode: 0644]
src/termios/tcdrain.c [new file with mode: 0644]
src/termios/tcflow.c [new file with mode: 0644]
src/termios/tcflush.c [new file with mode: 0644]
src/termios/tcgetattr.c [new file with mode: 0644]
src/termios/tcgetsid.c [new file with mode: 0644]
src/termios/tcsendbreak.c [new file with mode: 0644]
src/termios/tcsetattr.c [new file with mode: 0644]
src/thread/__futex.c [new file with mode: 0644]
src/thread/__lock.c [new file with mode: 0644]
src/thread/__set_thread_area.c [new file with mode: 0644]
src/thread/__timedwait.c [new file with mode: 0644]
src/thread/__unmapself.c [new file with mode: 0644]
src/thread/__wait.c [new file with mode: 0644]
src/thread/__wake.c [new file with mode: 0644]
src/thread/cancellation.c [new file with mode: 0644]
src/thread/clone.c [new file with mode: 0644]
src/thread/i386/__unmapself.s [new file with mode: 0644]
src/thread/i386/clone.s [new file with mode: 0644]
src/thread/pthread_attr_destroy.c [new file with mode: 0644]
src/thread/pthread_attr_getdetachstate.c [new file with mode: 0644]
src/thread/pthread_attr_getguardsize.c [new file with mode: 0644]
src/thread/pthread_attr_getscope.c [new file with mode: 0644]
src/thread/pthread_attr_getstacksize.c [new file with mode: 0644]
src/thread/pthread_attr_init.c [new file with mode: 0644]
src/thread/pthread_attr_setdetachstate.c [new file with mode: 0644]
src/thread/pthread_attr_setguardsize.c [new file with mode: 0644]
src/thread/pthread_attr_setscope.c [new file with mode: 0644]
src/thread/pthread_attr_setstacksize.c [new file with mode: 0644]
src/thread/pthread_barrier_destroy.c [new file with mode: 0644]
src/thread/pthread_barrier_init.c [new file with mode: 0644]
src/thread/pthread_barrier_wait.c [new file with mode: 0644]
src/thread/pthread_cancel.c [new file with mode: 0644]
src/thread/pthread_cond_broadcast.c [new file with mode: 0644]
src/thread/pthread_cond_destroy.c [new file with mode: 0644]
src/thread/pthread_cond_init.c [new file with mode: 0644]
src/thread/pthread_cond_signal.c [new file with mode: 0644]
src/thread/pthread_cond_timedwait.c [new file with mode: 0644]
src/thread/pthread_cond_wait.c [new file with mode: 0644]
src/thread/pthread_create.c [new file with mode: 0644]
src/thread/pthread_detach.c [new file with mode: 0644]
src/thread/pthread_equal.c [new file with mode: 0644]
src/thread/pthread_exit.c [new file with mode: 0644]
src/thread/pthread_getspecific.c [new file with mode: 0644]
src/thread/pthread_join.c [new file with mode: 0644]
src/thread/pthread_key_create.c [new file with mode: 0644]
src/thread/pthread_key_delete.c [new file with mode: 0644]
src/thread/pthread_kill.c [new file with mode: 0644]
src/thread/pthread_mutex_destroy.c [new file with mode: 0644]
src/thread/pthread_mutex_init.c [new file with mode: 0644]
src/thread/pthread_mutex_lock.c [new file with mode: 0644]
src/thread/pthread_mutex_timedlock.c [new file with mode: 0644]
src/thread/pthread_mutex_trylock.c [new file with mode: 0644]
src/thread/pthread_mutex_unlock.c [new file with mode: 0644]
src/thread/pthread_mutexattr_destroy.c [new file with mode: 0644]
src/thread/pthread_mutexattr_gettype.c [new file with mode: 0644]
src/thread/pthread_mutexattr_init.c [new file with mode: 0644]
src/thread/pthread_mutexattr_settype.c [new file with mode: 0644]
src/thread/pthread_once.c [new file with mode: 0644]
src/thread/pthread_rwlock_destroy.c [new file with mode: 0644]
src/thread/pthread_rwlock_init.c [new file with mode: 0644]
src/thread/pthread_rwlock_rdlock.c [new file with mode: 0644]
src/thread/pthread_rwlock_timedrdlock.c [new file with mode: 0644]
src/thread/pthread_rwlock_timedwrlock.c [new file with mode: 0644]
src/thread/pthread_rwlock_tryrdlock.c [new file with mode: 0644]
src/thread/pthread_rwlock_trywrlock.c [new file with mode: 0644]
src/thread/pthread_rwlock_unlock.c [new file with mode: 0644]
src/thread/pthread_rwlock_wrlock.c [new file with mode: 0644]
src/thread/pthread_self.c [new file with mode: 0644]
src/thread/pthread_setcancelstate.c [new file with mode: 0644]
src/thread/pthread_setcanceltype.c [new file with mode: 0644]
src/thread/pthread_setspecific.c [new file with mode: 0644]
src/thread/pthread_spin_destroy.c [new file with mode: 0644]
src/thread/pthread_spin_init.c [new file with mode: 0644]
src/thread/pthread_spin_lock.c [new file with mode: 0644]
src/thread/pthread_spin_trylock.c [new file with mode: 0644]
src/thread/pthread_spin_unlock.c [new file with mode: 0644]
src/thread/pthread_testcancel.c [new file with mode: 0644]
src/time/__asctime.c [new file with mode: 0644]
src/time/__time.h [new file with mode: 0644]
src/time/__time_to_tm.c [new file with mode: 0644]
src/time/__tm_to_time.c [new file with mode: 0644]
src/time/asctime.c [new file with mode: 0644]
src/time/asctime_r.c [new file with mode: 0644]
src/time/clock.c [new file with mode: 0644]
src/time/clock_gettime.c [new file with mode: 0644]
src/time/ctime.c [new file with mode: 0644]
src/time/ctime_r.c [new file with mode: 0644]
src/time/difftime.c [new file with mode: 0644]
src/time/gettimeofday.c [new file with mode: 0644]
src/time/gmtime.c [new file with mode: 0644]
src/time/gmtime_r.c [new file with mode: 0644]
src/time/localtime.c [new file with mode: 0644]
src/time/localtime_r.c [new file with mode: 0644]
src/time/mktime.c [new file with mode: 0644]
src/time/nanosleep.c [new file with mode: 0644]
src/time/strftime.c [new file with mode: 0644]
src/time/strptime.c [new file with mode: 0644]
src/time/time.c [new file with mode: 0644]
src/time/times.c [new file with mode: 0644]
src/time/timezone.s [new file with mode: 0644]
src/time/tzset.c [new file with mode: 0644]
src/time/utime.c [new file with mode: 0644]
src/unistd/_exit.c [new file with mode: 0644]
src/unistd/access.c [new file with mode: 0644]
src/unistd/alarm.c [new file with mode: 0644]
src/unistd/chdir.c [new file with mode: 0644]
src/unistd/chown.c [new file with mode: 0644]
src/unistd/close.c [new file with mode: 0644]
src/unistd/confstr.c [new file with mode: 0644]
src/unistd/ctermid.c [new file with mode: 0644]
src/unistd/dup.c [new file with mode: 0644]
src/unistd/dup2.c [new file with mode: 0644]
src/unistd/faccessat.c [new file with mode: 0644]
src/unistd/fchdir.c [new file with mode: 0644]
src/unistd/fchown.c [new file with mode: 0644]
src/unistd/fchownat.c [new file with mode: 0644]
src/unistd/fdatasync.c [new file with mode: 0644]
src/unistd/fsync.c [new file with mode: 0644]
src/unistd/ftruncate.c [new file with mode: 0644]
src/unistd/getcwd.c [new file with mode: 0644]
src/unistd/getegid.c [new file with mode: 0644]
src/unistd/geteuid.c [new file with mode: 0644]
src/unistd/getgid.c [new file with mode: 0644]
src/unistd/getgroups.c [new file with mode: 0644]
src/unistd/gethostname.c [new file with mode: 0644]
src/unistd/getlogin.c [new file with mode: 0644]
src/unistd/getlogin_r.c [new file with mode: 0644]
src/unistd/getpgid.c [new file with mode: 0644]
src/unistd/getpgrp.c [new file with mode: 0644]
src/unistd/getpid.c [new file with mode: 0644]
src/unistd/getppid.c [new file with mode: 0644]
src/unistd/getsid.c [new file with mode: 0644]
src/unistd/getuid.c [new file with mode: 0644]
src/unistd/isatty.c [new file with mode: 0644]
src/unistd/lchown.c [new file with mode: 0644]
src/unistd/link.c [new file with mode: 0644]
src/unistd/linkat.c [new file with mode: 0644]
src/unistd/lseek.c [new file with mode: 0644]
src/unistd/nice.c [new file with mode: 0644]
src/unistd/pause.c [new file with mode: 0644]
src/unistd/pipe.c [new file with mode: 0644]
src/unistd/pread.c [new file with mode: 0644]
src/unistd/pwrite.c [new file with mode: 0644]
src/unistd/read.c [new file with mode: 0644]
src/unistd/readlink.c [new file with mode: 0644]
src/unistd/readlinkat.c [new file with mode: 0644]
src/unistd/readv.c [new file with mode: 0644]
src/unistd/renameat.c [new file with mode: 0644]
src/unistd/rmdir.c [new file with mode: 0644]
src/unistd/setegid.c [new file with mode: 0644]
src/unistd/seteuid.c [new file with mode: 0644]
src/unistd/setgid.c [new file with mode: 0644]
src/unistd/setpgid.c [new file with mode: 0644]
src/unistd/setpgrp.c [new file with mode: 0644]
src/unistd/setregid.c [new file with mode: 0644]
src/unistd/setreuid.c [new file with mode: 0644]
src/unistd/setsid.c [new file with mode: 0644]
src/unistd/setuid.c [new file with mode: 0644]
src/unistd/sleep.c [new file with mode: 0644]
src/unistd/symlink.c [new file with mode: 0644]
src/unistd/symlinkat.c [new file with mode: 0644]
src/unistd/sync.c [new file with mode: 0644]
src/unistd/tcgetpgrp.c [new file with mode: 0644]
src/unistd/tcsetpgrp.c [new file with mode: 0644]
src/unistd/truncate.c [new file with mode: 0644]
src/unistd/ttyname.c [new file with mode: 0644]
src/unistd/ttyname_r.c [new file with mode: 0644]
src/unistd/ualarm.c [new file with mode: 0644]
src/unistd/unlink.c [new file with mode: 0644]
src/unistd/unlinkat.c [new file with mode: 0644]
src/unistd/usleep.c [new file with mode: 0644]
src/unistd/write.c [new file with mode: 0644]
src/unistd/writev.c [new file with mode: 0644]
tools/gen-musl-gcc.sh [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..223ede7
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644 (file)
index 0000000..30a74a2
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,31 @@
+musl as a whole is licensed under the GNU LGPL version 2.1 or later.
+See the file COPYING for the text of this license.
+
+See below for the copyright status on all code included in musl:
+
+The TRE regular expression implementation (src/regex/reg* and
+src/regex/tre*) is Copyright Â© 2001-2006 Ville Laurikari and licensed
+under the terms of the GNU LGPL version 2.1 or later. The included
+version was heavily modified in Spring 2006 by Rich Felker in the
+interests of size, simplicity, and namespace cleanliness.
+
+Most of the math library code (src/math/*) is Copyright Â© 1993 Sun
+Microsystems, Inc. Some files are Copyright Â© 2003 Steven G. Kargl and
+labelled as such. All have been licensed under extremely permissive
+terms which are compatible with the GNU LGPL. See the comments in the
+individual files for details.
+
+The implementation of DES for crypt (src/misc/crypt.c) is Copyright Â©
+1994 David Burren. It is licensed under a BSD license compatible with
+the GNU LGPL.
+
+All files which have no copyright comments are original works
+Copyright Â© 2005-2011 Rich Felker, the main author of this library.
+The decision to exclude such comments is intentional, as it should be
+possible to carry around the complete source code on tiny storage
+media. All public header files (include/*) should be treated as Public
+Domain as they intentionally contain no content which can be covered
+by copyright. Some source modules may fall in this category as well.
+If you believe that a file is so trivial that it should be in the
+Public Domain, please contact me and, if I agree, I will explicitly
+release it from copyright.
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..2470a5b
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,61 @@
+
+A quick-and-simple guide to installing musl:
+
+
+STEP 1: Configuration
+
+Edit config.mak to override installation prefix, compiler options,
+etc. as needed. The defaults should be okay for trying out musl with
+static linking only. The only arch supported at present is i386. If
+you're on an x86_64 machine, you can add -m32 to the compiler options
+to build a working 32bit musl. In this case you will also need to add
+-m32 in two locations in the generated tools/musl-gcc script if you
+intend to use it.
+
+DO NOT set the prefix to /, /usr, or even /usr/local unless you really
+know what you're doing! You'll probably break your system such that
+you'll no longer be able to compile and link programs against glibc!
+This kind of setup should only be used if you're building a system
+where musl is the default/primary/only libc.
+
+The default prefix is /usr/local/musl for a reason, but some people
+may prefer /opt/musl or $HOME/musl.
+
+
+STEP 2: Compiling
+
+Run "make". (GNU make is required.)
+
+
+STEP 3: Installation
+
+With appropriate privileges, run "make install".
+
+
+STEP 4: Using the gcc wrapper.
+
+musl comes with a script "musl-gcc" (installed in /usr/local/bin by
+default) that can be used to compile and link C programs against musl.
+It requires a version of gcc with the -wrapper option (gcc 4.x should
+work). For example:
+
+cat > hello.c <<EOF
+#include <stdio.h>
+int main()
+{
+       printf("hello, world!\n");
+       return 0;
+}
+EOF
+musl-gcc hello.c
+./a.out
+
+For compiling programs that use autoconf, you'll need to configure
+them with a command like this:
+
+CC=musl-gcc ./configure
+
+Be aware that (at present) libraries linked against glibc are unlikely
+to be usable, and the musl-gcc wrapper inhibits search of the system
+library paths in any case. You'll need to compile any prerequisite
+libraries (like ncurses, glib, etc.) yourself.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e4235cb
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,97 @@
+#
+# Makefile for musl (requires GNU make)
+#
+# This is how simple every makefile should be...
+# No, I take that back - actually most should be less than half this size.
+#
+# Use config.mak to override any of the following variables.
+# Do not make changes here.
+#
+
+exec_prefix = /usr/local
+bindir = $(exec_prefix)/bin
+
+prefix = /usr/local/musl
+includedir = $(prefix)/include
+libdir = $(prefix)/lib
+
+SRCS = $(sort $(wildcard src/*/*.c))
+OBJS = $(SRCS:.c=.o)
+LOBJS = $(OBJS:.o=.lo)
+GENH = include/bits/alltypes.h
+
+CFLAGS  = -Os -nostdinc -ffreestanding -pipe
+LDFLAGS = -nostdlib -shared -Wl,-Bsymbolic
+INC     = -I./include -I./src/internal
+PIC     = -fPIC
+AR      = $(CROSS_COMPILE)ar
+RANLIB  = $(CROSS_COMPILE)ranlib
+OBJCOPY = $(CROSS_COMPILE)objcopy
+
+ALL_INCLUDES = $(sort $(wildcard include/*.h include/*/*.h) $(GENH))
+
+EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv
+EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
+CRT_LIBS = lib/crt1.o lib/crti.o lib/crtn.o
+LIBC_LIBS = lib/libc.a
+ALL_LIBS = $(LIBC_LIBS) $(CRT_LIBS) $(EMPTY_LIBS)
+
+ALL_TOOLS = tools/musl-gcc
+
+-include config.mak
+
+all: $(ALL_LIBS) $(ALL_TOOLS)
+
+install: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%) $(ALL_TOOLS:tools/%=$(DESTDIR)$(bindir)/%)
+
+clean:
+       rm -f crt/*.o
+       rm -f $(OBJS)
+       rm -f $(LOBJS)
+       rm -f $(ALL_LIBS) lib/*
+       rm -f $(ALL_TOOLS)
+       rm -f $(GENH) 
+
+include/bits/alltypes.h: include/bits/alltypes.h.sh
+       sh $< > $@
+
+%.o: $(ARCH)/%.s
+       $(CC) $(CFLAGS) $(INC) -c -o $@ $<
+
+%.o: %.c $(GENH)
+       $(CC) $(CFLAGS) $(INC) -c -o $@ $<
+
+%.lo: $(ARCH)/%.s
+       $(CC) $(CFLAGS) $(INC) $(PIC) -c -o $@ $<
+
+%.lo: %.c $(GENH)
+       $(CC) $(CFLAGS) $(INC) $(PIC) -c -o $@ $<
+
+lib/libc.so: $(LOBJS)
+       $(CC) $(LDFLAGS) -o $@ $(LOBJS) -lgcc
+       $(OBJCOPY) --weaken $@
+
+lib/libc.a: $(OBJS)
+       rm -f $@
+       $(AR) rc $@ $(OBJS)
+       $(RANLIB) $@
+
+$(EMPTY_LIBS):
+       $(AR) rc $@
+
+lib/%.o: crt/%.o
+       cp $< $@
+
+tools/musl-gcc: tools/gen-musl-gcc.sh config.mak
+       sh $< "$(prefix)" > $@ || { rm -f $@ ; exit 1 ; }
+       chmod +x $@
+
+$(DESTDIR)$(bindir)/%: tools/%
+       install -D $< $@
+
+$(DESTDIR)$(prefix)/%: %
+       install -D -m 644 $< $@
+
+.PRECIOUS: $(CRT_LIBS:lib/%=crt/%)
+
+.PHONY: all clean install
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..a57541c
--- /dev/null
+++ b/README
@@ -0,0 +1,44 @@
+
+musl libc - a new standard library to power a new generation of
+Linux-based devices. musl is lightweight, fast, simple, free, and
+strives to be correct in the sense of standards-conformance and
+safety.
+
+musl is an alternative to glibc, eglibc, uClibc, dietlibc, and klibc.
+For reasons why one might prefer musl, please see the FAQ and libc
+comparison chart on the project website,
+
+    http://www.etalabs.net/musl/
+
+For installation instructions, see the INSTALL file.
+
+Please refer to the COPYRIGHT file for details on the copyright status
+of code included in musl, and the COPYING file for the license (LGPL)
+under which the library as a whole is distributed.
+
+
+
+Greetings libc hackers!
+
+This package is an _alpha_ release of musl, intended for the curious
+and the adventurous. While it can be used to build a complete small
+Linux system (musl is self-hosted on the system I use to develop it),
+at this point doing so requires a lot of manual effort. Nonetheless, I
+hope low-level Linux enthusiasts will try out building some compact
+static binaries with musl using the provided gcc wrapper (which allows
+you to link programs with musl on a "standard" glibc Linux system),
+find whatever embarassing bugs I've let slip through, and provide
+feedback on issues encountered building various software against musl.
+
+Please visit #musl on Freenode IRC or contact me via email at dalias
+AT etalabs DOT net for bug reports, support requests, or to get
+involved in development. As this has been a one-person project so far,
+mailing lists will be setup in due time on an as-needed basis.
+
+Thank you for trying out musl.
+
+Cheers,
+
+Rich Felker / dalias
+
+
diff --git a/crt/crt1.c b/crt/crt1.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/crt/crti.c b/crt/crti.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/crt/crtn.c b/crt/crtn.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/crt/i386/crt1.s b/crt/i386/crt1.s
new file mode 100644 (file)
index 0000000..050adec
--- /dev/null
@@ -0,0 +1,17 @@
+.text
+.global _start
+_start:
+       xorl %ebp,%ebp
+       popl %ecx
+       movl %esp,%eax
+       andl $-16,%esp
+       pushl %esp
+       pushl %esp
+       pushl %edx
+       pushl $0
+       pushl $0
+       pushl %eax
+       pushl %ecx
+       pushl $main
+       call __libc_start_main
+.L0:   jmp .L0
diff --git a/dist/config.mak b/dist/config.mak
new file mode 100644 (file)
index 0000000..5120552
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# musl config.mak template (original in dist/config.mak)
+#
+
+# Target CPU architecture. Supported values: i386
+ARCH = i386
+
+# Installation prefix. DO NOT use /, /usr, or /usr/local !
+prefix = /usr/local/musl
+
+# Installation prefix for musl-gcc compiler wrapper.
+exec_prefix = /usr/local
+
+# Uncomment if you want to build i386 musl on a 64-bit host
+#CFLAGS += -m32
+
+# Uncomment for smaller code size.
+#CFLAGS += -fomit-frame-pointer -mno-accumulate-outgoing-args
+
+# Uncomment for warnings (as errors). Might need tuning to your gcc version.
+#CFLAGS += -Werror -Wall -Wpointer-arith -Wcast-align -Wno-parentheses -Wno-char-subscripts -Wno-uninitialized -Wno-sequence-point -Wno-missing-braces -Wno-unused-value
+#CFLAGS += -Wno-pointer-sign
+
+# Uncomment if you want to build a shared library (experimental).
+#LIBC_LIBS += lib/libc.so
diff --git a/include/alloca.h b/include/alloca.h
new file mode 100644 (file)
index 0000000..ac78e46
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef        _ALLOCA_H
+#define        _ALLOCA_H
+
+#define        __NEED_size_t
+#include <bits/alltypes.h>
+
+void *alloca(size_t);
+
+#endif
diff --git a/include/arpa/inet.h b/include/arpa/inet.h
new file mode 100644 (file)
index 0000000..9342713
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _ARPA_INET_H
+#define        _ARPA_INET_H
+
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#define __NEED_socklen_t
+#define __NEED_in_addr_t
+#define __NEED_in_port_t
+#define __NEED_uint16_t
+#define __NEED_uint32_t
+#define __NEED_struct_in_addr
+
+#include <bits/alltypes.h>
+
+uint32_t htonl(uint32_t);
+uint16_t htons(uint16_t);
+uint32_t ntohl(uint32_t);
+uint16_t ntohs(uint16_t);
+
+in_addr_t inet_addr (const char *);
+char *inet_ntoa (struct in_addr);
+int inet_pton (int, const char *, void *);
+const char *inet_ntop (int, const void *, char *, socklen_t);
+
+int inet_aton (const char *, struct in_addr *); /* nonstandard but widely used */
+
+#undef INET_ADDRSTRLEN
+#undef INET6_ADDRSTRLEN
+#define INET_ADDRSTRLEN  16
+#define INET6_ADDRSTRLEN 46
+
+#endif
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
new file mode 100644 (file)
index 0000000..0f85460
--- /dev/null
@@ -0,0 +1,465 @@
+#ifndef _ARPA_NAMESER_H_
+#define _ARPA_NAMESER_H_
+
+#define __NAMESER      19991006
+#define NS_PACKETSZ    512
+#define NS_MAXDNAME    1025
+#define NS_MAXMSG      65535
+#define NS_MAXCDNAME   255
+#define NS_MAXLABEL    63
+#define NS_HFIXEDSZ    12
+#define NS_QFIXEDSZ    4
+#define NS_RRFIXEDSZ   10
+#define NS_INT32SZ     4
+#define NS_INT16SZ     2
+#define NS_INT8SZ      1
+#define NS_INADDRSZ    4
+#define NS_IN6ADDRSZ   16
+#define NS_CMPRSFLGS   0xc0
+#define NS_DEFAULTPORT 53
+
+typedef enum __ns_sect {
+       ns_s_qd = 0,
+       ns_s_zn = 0,
+       ns_s_an = 1,
+       ns_s_pr = 1,
+       ns_s_ns = 2,
+       ns_s_ud = 2,
+       ns_s_ar = 3,
+       ns_s_max = 4
+} ns_sect;
+
+typedef struct __ns_msg {
+       const unsigned char *_msg, *_eom;
+       uint16_t _id, _flags, _counts[ns_s_max];
+       const unsigned char *_sections[ns_s_max];
+       ns_sect _sect;
+       int _rrnum;
+       const unsigned char *_msg_ptr;
+} ns_msg;
+
+struct _ns_flagdata {  int mask, shift;  };
+extern const struct _ns_flagdata _ns_flagdata[];
+
+#define ns_msg_id(handle) ((handle)._id + 0)
+#define ns_msg_base(handle) ((handle)._msg + 0)
+#define ns_msg_end(handle) ((handle)._eom + 0)
+#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
+
+typedef        struct __ns_rr {
+       char            name[NS_MAXDNAME];
+       uint16_t        type;
+       uint16_t        rr_class;
+       uint32_t        ttl;
+       uint16_t        rdlength;
+       const unsigned char *rdata;
+} ns_rr;
+
+#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
+#define ns_rr_type(rr) ((ns_type)((rr).type + 0))
+#define ns_rr_class(rr)        ((ns_class)((rr).rr_class + 0))
+#define ns_rr_ttl(rr)  ((rr).ttl + 0)
+#define ns_rr_rdlen(rr)        ((rr).rdlength + 0)
+#define ns_rr_rdata(rr)        ((rr).rdata + 0)
+
+typedef enum __ns_flag {
+       ns_f_qr,
+       ns_f_opcode,
+       ns_f_aa,
+       ns_f_tc,
+       ns_f_rd,
+       ns_f_ra,
+       ns_f_z,
+       ns_f_ad,
+       ns_f_cd,
+       ns_f_rcode,
+       ns_f_max
+} ns_flag;
+
+typedef enum __ns_opcode {
+       ns_o_query = 0,
+       ns_o_iquery = 1,
+       ns_o_status = 2,
+       ns_o_notify = 4,
+       ns_o_update = 5,
+       ns_o_max = 6
+} ns_opcode;
+
+typedef        enum __ns_rcode {
+       ns_r_noerror = 0,
+       ns_r_formerr = 1,
+       ns_r_servfail = 2,
+       ns_r_nxdomain = 3,
+       ns_r_notimpl = 4,
+       ns_r_refused = 5,
+       ns_r_yxdomain = 6,
+       ns_r_yxrrset = 7,
+       ns_r_nxrrset = 8,
+       ns_r_notauth = 9,
+       ns_r_notzone = 10,
+       ns_r_max = 11,
+       ns_r_badvers = 16,
+       ns_r_badsig = 16,
+       ns_r_badkey = 17,
+       ns_r_badtime = 18
+} ns_rcode;
+
+typedef enum __ns_update_operation {
+       ns_uop_delete = 0,
+       ns_uop_add = 1,
+       ns_uop_max = 2
+} ns_update_operation;
+
+struct ns_tsig_key {
+        char name[NS_MAXDNAME], alg[NS_MAXDNAME];
+        unsigned char *data;
+        int len;
+};
+typedef struct ns_tsig_key ns_tsig_key;
+
+struct ns_tcp_tsig_state {
+       int counter;
+       struct dst_key *key;
+       void *ctx;
+       unsigned char sig[NS_PACKETSZ];
+       int siglen;
+};
+typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
+
+#define NS_TSIG_FUDGE 300
+#define NS_TSIG_TCP_COUNT 100
+#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
+
+#define NS_TSIG_ERROR_NO_TSIG -10
+#define NS_TSIG_ERROR_NO_SPACE -11
+#define NS_TSIG_ERROR_FORMERR -12
+
+typedef enum __ns_type {
+       ns_t_invalid = 0,
+       ns_t_a = 1,
+       ns_t_ns = 2,
+       ns_t_md = 3,
+       ns_t_mf = 4,
+       ns_t_cname = 5,
+       ns_t_soa = 6,
+       ns_t_mb = 7,
+       ns_t_mg = 8,
+       ns_t_mr = 9,
+       ns_t_null = 10,
+       ns_t_wks = 11,
+       ns_t_ptr = 12,
+       ns_t_hinfo = 13,
+       ns_t_minfo = 14,
+       ns_t_mx = 15,
+       ns_t_txt = 16,
+       ns_t_rp = 17,
+       ns_t_afsdb = 18,
+       ns_t_x25 = 19,
+       ns_t_isdn = 20,
+       ns_t_rt = 21,
+       ns_t_nsap = 22,
+       ns_t_nsap_ptr = 23,
+       ns_t_sig = 24,
+       ns_t_key = 25,
+       ns_t_px = 26,
+       ns_t_gpos = 27,
+       ns_t_aaaa = 28,
+       ns_t_loc = 29,
+       ns_t_nxt = 30,
+       ns_t_eid = 31,
+       ns_t_nimloc = 32,
+       ns_t_srv = 33,
+       ns_t_atma = 34,
+       ns_t_naptr = 35,
+       ns_t_kx = 36,
+       ns_t_cert = 37,
+       ns_t_a6 = 38,
+       ns_t_dname = 39,
+       ns_t_sink = 40,
+       ns_t_opt = 41,
+       ns_t_apl = 42,
+       ns_t_tkey = 249,
+       ns_t_tsig = 250,
+       ns_t_ixfr = 251,
+       ns_t_axfr = 252,
+       ns_t_mailb = 253,
+       ns_t_maila = 254,
+       ns_t_any = 255,
+       ns_t_zxfr = 256,
+       ns_t_max = 65536
+} ns_type;
+
+#define        ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
+                     (t) == ns_t_mailb || (t) == ns_t_maila)
+#define        ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
+#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
+#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
+#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
+                      (t) == ns_t_zxfr)
+
+typedef enum __ns_class {
+       ns_c_invalid = 0,
+       ns_c_in = 1,
+       ns_c_2 = 2,
+       ns_c_chaos = 3,
+       ns_c_hs = 4,
+       ns_c_none = 254,
+       ns_c_any = 255,
+       ns_c_max = 65536
+} ns_class;
+
+typedef enum __ns_key_types {
+       ns_kt_rsa = 1,
+       ns_kt_dh  = 2,
+       ns_kt_dsa = 3,
+       ns_kt_private = 254
+} ns_key_types;
+
+typedef enum __ns_cert_types {
+       cert_t_pkix = 1,
+       cert_t_spki = 2,
+       cert_t_pgp  = 3,
+       cert_t_url  = 253,
+       cert_t_oid  = 254
+} ns_cert_types;
+
+#define        NS_KEY_TYPEMASK         0xC000
+#define        NS_KEY_TYPE_AUTH_CONF   0x0000
+#define        NS_KEY_TYPE_CONF_ONLY   0x8000
+#define        NS_KEY_TYPE_AUTH_ONLY   0x4000
+#define        NS_KEY_TYPE_NO_KEY      0xC000
+#define        NS_KEY_NO_AUTH          0x8000
+#define        NS_KEY_NO_CONF          0x4000
+#define        NS_KEY_RESERVED2        0x2000
+#define        NS_KEY_EXTENDED_FLAGS   0x1000
+#define        NS_KEY_RESERVED4        0x0800
+#define        NS_KEY_RESERVED5        0x0400
+#define        NS_KEY_NAME_TYPE        0x0300
+#define        NS_KEY_NAME_USER        0x0000
+#define        NS_KEY_NAME_ENTITY      0x0200
+#define        NS_KEY_NAME_ZONE        0x0100
+#define        NS_KEY_NAME_RESERVED    0x0300
+#define        NS_KEY_RESERVED8        0x0080
+#define        NS_KEY_RESERVED9        0x0040
+#define        NS_KEY_RESERVED10       0x0020
+#define        NS_KEY_RESERVED11       0x0010
+#define        NS_KEY_SIGNATORYMASK    0x000F
+#define        NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
+                                 NS_KEY_RESERVED4 | \
+                                 NS_KEY_RESERVED5 | \
+                                 NS_KEY_RESERVED8 | \
+                                 NS_KEY_RESERVED9 | \
+                                 NS_KEY_RESERVED10 | \
+                                 NS_KEY_RESERVED11 )
+#define NS_KEY_RESERVED_BITMASK2 0xFFFF
+#define        NS_ALG_MD5RSA           1
+#define        NS_ALG_DH               2
+#define        NS_ALG_DSA              3
+#define        NS_ALG_DSS              NS_ALG_DSA
+#define        NS_ALG_EXPIRE_ONLY      253
+#define        NS_ALG_PRIVATE_OID      254
+
+#define NS_KEY_PROT_TLS         1
+#define NS_KEY_PROT_EMAIL       2
+#define NS_KEY_PROT_DNSSEC      3
+#define NS_KEY_PROT_IPSEC       4
+#define NS_KEY_PROT_ANY                255
+
+#define        NS_MD5RSA_MIN_BITS       512
+#define        NS_MD5RSA_MAX_BITS      4096
+#define        NS_MD5RSA_MAX_BYTES     ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
+#define        NS_MD5RSA_MAX_BASE64    (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
+#define NS_MD5RSA_MIN_SIZE     ((NS_MD5RSA_MIN_BITS+7)/8)
+#define NS_MD5RSA_MAX_SIZE     ((NS_MD5RSA_MAX_BITS+7)/8)
+
+#define NS_DSA_SIG_SIZE         41
+#define NS_DSA_MIN_SIZE         213
+#define NS_DSA_MAX_BYTES        405
+
+#define        NS_SIG_TYPE     0
+#define        NS_SIG_ALG      2
+#define        NS_SIG_LABELS   3
+#define        NS_SIG_OTTL     4
+#define        NS_SIG_EXPIR    8
+#define        NS_SIG_SIGNED   12
+#define        NS_SIG_FOOT     16
+#define        NS_SIG_SIGNER   18
+#define        NS_NXT_BITS 8
+#define        NS_NXT_BIT_SET(  n,p) (p[(n)/NS_NXT_BITS] |=  (0x80>>((n)%NS_NXT_BITS)))
+#define        NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
+#define        NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] &   (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_MAX 127
+
+#define NS_OPT_DNSSEC_OK        0x8000U
+#define NS_OPT_NSID            3
+
+#define NS_GET16(s, cp) do { \
+       register const unsigned char *t_cp = (const unsigned char *)(cp); \
+       (s) = ((uint16_t)t_cp[0] << 8) \
+           | ((uint16_t)t_cp[1]) \
+           ; \
+       (cp) += NS_INT16SZ; \
+} while (0)
+
+#define NS_GET32(l, cp) do { \
+       register const unsigned char *t_cp = (const unsigned char *)(cp); \
+       (l) = ((uint32_t)t_cp[0] << 24) \
+           | ((uint32_t)t_cp[1] << 16) \
+           | ((uint32_t)t_cp[2] << 8) \
+           | ((uint32_t)t_cp[3]) \
+           ; \
+       (cp) += NS_INT32SZ; \
+} while (0)
+
+#define NS_PUT16(s, cp) do { \
+       register uint16_t t_s = (uint16_t)(s); \
+       register unsigned char *t_cp = (unsigned char *)(cp); \
+       *t_cp++ = t_s >> 8; \
+       *t_cp   = t_s; \
+       (cp) += NS_INT16SZ; \
+} while (0)
+
+#define NS_PUT32(l, cp) do { \
+       register uint32_t t_l = (uint32_t)(l); \
+       register unsigned char *t_cp = (unsigned char *)(cp); \
+       *t_cp++ = t_l >> 24; \
+       *t_cp++ = t_l >> 16; \
+       *t_cp++ = t_l >> 8; \
+       *t_cp   = t_l; \
+       (cp) += NS_INT32SZ; \
+} while (0)
+
+
+
+
+#define        __BIND          19950621
+
+typedef struct {
+       unsigned        id :16;
+#if __BYTE_ORDER == __BIG_ENDIAN
+       unsigned        qr: 1;
+       unsigned        opcode: 4;
+       unsigned        aa: 1;
+       unsigned        tc: 1;
+       unsigned        rd: 1;
+       unsigned        ra: 1;
+       unsigned        unused :1;
+       unsigned        ad: 1;
+       unsigned        cd: 1;
+       unsigned        rcode :4;
+#else
+       unsigned        rd :1;
+       unsigned        tc :1;
+       unsigned        aa :1;
+       unsigned        opcode :4;
+       unsigned        qr :1;
+       unsigned        rcode :4;
+       unsigned        cd: 1;
+       unsigned        ad: 1;
+       unsigned        unused :1;
+       unsigned        ra :1;
+#endif
+       unsigned        qdcount :16;
+       unsigned        ancount :16;
+       unsigned        nscount :16;
+       unsigned        arcount :16;
+} HEADER;
+
+#define PACKETSZ       NS_PACKETSZ
+#define MAXDNAME       NS_MAXDNAME
+#define MAXCDNAME      NS_MAXCDNAME
+#define MAXLABEL       NS_MAXLABEL
+#define        HFIXEDSZ        NS_HFIXEDSZ
+#define QFIXEDSZ       NS_QFIXEDSZ
+#define RRFIXEDSZ      NS_RRFIXEDSZ
+#define        INT32SZ         NS_INT32SZ
+#define        INT16SZ         NS_INT16SZ
+#define INT8SZ         NS_INT8SZ
+#define        INADDRSZ        NS_INADDRSZ
+#define        IN6ADDRSZ       NS_IN6ADDRSZ
+#define        INDIR_MASK      NS_CMPRSFLGS
+#define NAMESERVER_PORT        NS_DEFAULTPORT
+
+#define S_ZONE         ns_s_zn
+#define S_PREREQ       ns_s_pr
+#define S_UPDATE       ns_s_ud
+#define S_ADDT         ns_s_ar
+
+#define QUERY          ns_o_query
+#define IQUERY         ns_o_iquery
+#define STATUS         ns_o_status
+#define        NS_NOTIFY_OP    ns_o_notify
+#define        NS_UPDATE_OP    ns_o_update
+
+#define NOERROR                ns_r_noerror
+#define FORMERR                ns_r_formerr
+#define SERVFAIL       ns_r_servfail
+#define NXDOMAIN       ns_r_nxdomain
+#define NOTIMP         ns_r_notimpl
+#define REFUSED                ns_r_refused
+#define YXDOMAIN       ns_r_yxdomain
+#define YXRRSET                ns_r_yxrrset
+#define NXRRSET                ns_r_nxrrset
+#define NOTAUTH                ns_r_notauth
+#define NOTZONE                ns_r_notzone
+
+#define DELETE         ns_uop_delete
+#define ADD            ns_uop_add
+
+#define T_A            ns_t_a
+#define T_NS           ns_t_ns
+#define T_MD           ns_t_md
+#define T_MF           ns_t_mf
+#define T_CNAME                ns_t_cname
+#define T_SOA          ns_t_soa
+#define T_MB           ns_t_mb
+#define T_MG           ns_t_mg
+#define T_MR           ns_t_mr
+#define T_NULL         ns_t_null
+#define T_WKS          ns_t_wks
+#define T_PTR          ns_t_ptr
+#define T_HINFO                ns_t_hinfo
+#define T_MINFO                ns_t_minfo
+#define T_MX           ns_t_mx
+#define T_TXT          ns_t_txt
+#define        T_RP            ns_t_rp
+#define T_AFSDB                ns_t_afsdb
+#define T_X25          ns_t_x25
+#define T_ISDN         ns_t_isdn
+#define T_RT           ns_t_rt
+#define T_NSAP         ns_t_nsap
+#define T_NSAP_PTR     ns_t_nsap_ptr
+#define        T_SIG           ns_t_sig
+#define        T_KEY           ns_t_key
+#define        T_PX            ns_t_px
+#define        T_GPOS          ns_t_gpos
+#define        T_AAAA          ns_t_aaaa
+#define        T_LOC           ns_t_loc
+#define        T_NXT           ns_t_nxt
+#define        T_EID           ns_t_eid
+#define        T_NIMLOC        ns_t_nimloc
+#define        T_SRV           ns_t_srv
+#define T_ATMA         ns_t_atma
+#define T_NAPTR                ns_t_naptr
+#define T_A6           ns_t_a6
+#define T_DNAME                ns_t_dname
+#define        T_TSIG          ns_t_tsig
+#define        T_IXFR          ns_t_ixfr
+#define T_AXFR         ns_t_axfr
+#define T_MAILB                ns_t_mailb
+#define T_MAILA                ns_t_maila
+#define T_ANY          ns_t_any
+
+#define C_IN           ns_c_in
+#define C_CHAOS                ns_c_chaos
+#define C_HS           ns_c_hs
+#define C_NONE         ns_c_none
+#define C_ANY          ns_c_any
+
+#define        GETSHORT                NS_GET16
+#define        GETLONG                 NS_GET32
+#define        PUTSHORT                NS_PUT16
+#define        PUTLONG                 NS_PUT32
+
+#endif
diff --git a/include/arpa/telnet.h b/include/arpa/telnet.h
new file mode 100644 (file)
index 0000000..e2ad974
--- /dev/null
@@ -0,0 +1,251 @@
+#ifndef _ARPA_TELNET_H
+#define        _ARPA_TELNET_H
+
+#define        IAC     255
+#define        DONT    254
+#define        DO      253
+#define        WONT    252
+#define        WILL    251
+#define        SB      250
+#define        GA      249
+#define        EL      248
+#define        EC      247
+#define        AYT     246
+#define        AO      245
+#define        IP      244
+#define        BREAK   243
+#define        DM      242
+#define        NOP     241
+#define        SE      240
+#define EOR     239
+#define        ABORT   238
+#define        SUSP    237
+#define        xEOF    236
+
+#define SYNCH  242
+
+#define telcmds ((char [][6]){ "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0 })
+
+#define        TELCMD_FIRST    xEOF
+#define        TELCMD_LAST     IAC
+#define        TELCMD_OK(x)    ((unsigned int)(x) <= TELCMD_LAST && \
+                        (unsigned int)(x) >= TELCMD_FIRST)
+#define        TELCMD(x)       telcmds[(x)-TELCMD_FIRST]
+
+#define TELOPT_BINARY  0
+#define TELOPT_ECHO    1
+#define        TELOPT_RCP      2
+#define        TELOPT_SGA      3
+#define        TELOPT_NAMS     4
+#define        TELOPT_STATUS   5
+#define        TELOPT_TM       6
+#define        TELOPT_RCTE     7
+#define TELOPT_NAOL    8
+#define TELOPT_NAOP    9
+#define TELOPT_NAOCRD  10
+#define TELOPT_NAOHTS  11
+#define TELOPT_NAOHTD  12
+#define TELOPT_NAOFFD  13
+#define TELOPT_NAOVTS  14
+#define TELOPT_NAOVTD  15
+#define TELOPT_NAOLFD  16
+#define TELOPT_XASCII  17
+#define        TELOPT_LOGOUT   18
+#define        TELOPT_BM       19
+#define        TELOPT_DET      20
+#define        TELOPT_SUPDUP   21
+#define        TELOPT_SUPDUPOUTPUT 22
+#define        TELOPT_SNDLOC   23
+#define        TELOPT_TTYPE    24
+#define        TELOPT_EOR      25
+#define        TELOPT_TUID     26
+#define        TELOPT_OUTMRK   27
+#define        TELOPT_TTYLOC   28
+#define        TELOPT_3270REGIME 29
+#define        TELOPT_X3PAD    30
+#define        TELOPT_NAWS     31
+#define        TELOPT_TSPEED   32
+#define        TELOPT_LFLOW    33
+#define TELOPT_LINEMODE        34
+#define TELOPT_XDISPLOC        35
+#define TELOPT_OLD_ENVIRON 36
+#define        TELOPT_AUTHENTICATION 37/* Authenticate */
+#define        TELOPT_ENCRYPT  38
+#define TELOPT_NEW_ENVIRON 39
+#define        TELOPT_EXOPL    255
+
+
+#define        NTELOPTS        (1+TELOPT_NEW_ENVIRON)
+#ifdef TELOPTS
+char *telopts[NTELOPTS+1] = {
+       "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+       "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+       "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+       "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+       "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+       "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
+       "TACACS UID", "OUTPUT MARKING", "TTYLOC",
+       "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
+       "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
+       "ENCRYPT", "NEW-ENVIRON",
+       0,
+};
+#define        TELOPT_FIRST    TELOPT_BINARY
+#define        TELOPT_LAST     TELOPT_NEW_ENVIRON
+#define        TELOPT_OK(x)    ((unsigned int)(x) <= TELOPT_LAST)
+#define        TELOPT(x)       telopts[(x)-TELOPT_FIRST]
+#endif
+
+#define        TELQUAL_IS      0
+#define        TELQUAL_SEND    1
+#define        TELQUAL_INFO    2
+#define        TELQUAL_REPLY   2
+#define        TELQUAL_NAME    3
+
+#define        LFLOW_OFF               0
+#define        LFLOW_ON                1
+#define        LFLOW_RESTART_ANY       2
+#define        LFLOW_RESTART_XON       3
+
+
+#define        LM_MODE         1
+#define        LM_FORWARDMASK  2
+#define        LM_SLC          3
+
+#define        MODE_EDIT       0x01
+#define        MODE_TRAPSIG    0x02
+#define        MODE_ACK        0x04
+#define MODE_SOFT_TAB  0x08
+#define MODE_LIT_ECHO  0x10
+
+#define        MODE_MASK       0x1f
+
+#define MODE_FLOW              0x0100
+#define MODE_ECHO              0x0200
+#define MODE_INBIN             0x0400
+#define MODE_OUTBIN            0x0800
+#define MODE_FORCE             0x1000
+
+#define        SLC_SYNCH       1
+#define        SLC_BRK         2
+#define        SLC_IP          3
+#define        SLC_AO          4
+#define        SLC_AYT         5
+#define        SLC_EOR         6
+#define        SLC_ABORT       7
+#define        SLC_EOF         8
+#define        SLC_SUSP        9
+#define        SLC_EC          10
+#define        SLC_EL          11
+#define        SLC_EW          12
+#define        SLC_RP          13
+#define        SLC_LNEXT       14
+#define        SLC_XON         15
+#define        SLC_XOFF        16
+#define        SLC_FORW1       17
+#define        SLC_FORW2       18
+
+#define        NSLC            18
+
+#define        SLC_NAMELIST    "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
+                       "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
+                       "LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
+#ifdef SLC_NAMES
+char *slc_names[] = {
+       SLC_NAMELIST
+};
+#else
+extern char *slc_names[];
+#define        SLC_NAMES SLC_NAMELIST
+#endif
+
+#define        SLC_NAME_OK(x)  ((unsigned int)(x) <= NSLC)
+#define SLC_NAME(x)    slc_names[x]
+
+#define        SLC_NOSUPPORT   0
+#define        SLC_CANTCHANGE  1
+#define        SLC_VARIABLE    2
+#define        SLC_DEFAULT     3
+#define        SLC_LEVELBITS   0x03
+
+#define        SLC_FUNC        0
+#define        SLC_FLAGS       1
+#define        SLC_VALUE       2
+
+#define        SLC_ACK         0x80
+#define        SLC_FLUSHIN     0x40
+#define        SLC_FLUSHOUT    0x20
+
+#define        OLD_ENV_VAR     1
+#define        OLD_ENV_VALUE   0
+#define        NEW_ENV_VAR     0
+#define        NEW_ENV_VALUE   1
+#define        ENV_ESC         2
+#define ENV_USERVAR    3
+
+#define        AUTH_WHO_CLIENT         0
+#define        AUTH_WHO_SERVER         1
+#define        AUTH_WHO_MASK           1
+
+#define        AUTH_HOW_ONE_WAY        0
+#define        AUTH_HOW_MUTUAL         2
+#define        AUTH_HOW_MASK           2
+
+#define        AUTHTYPE_NULL           0
+#define        AUTHTYPE_KERBEROS_V4    1
+#define        AUTHTYPE_KERBEROS_V5    2
+#define        AUTHTYPE_SPX            3
+#define        AUTHTYPE_MINK           4
+#define        AUTHTYPE_CNT            5
+
+#define        AUTHTYPE_TEST           99
+
+#ifdef AUTH_NAMES
+char *authtype_names[] = {
+       "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
+};
+#else
+extern char *authtype_names[];
+#endif
+
+#define        AUTHTYPE_NAME_OK(x)     ((unsigned int)(x) < AUTHTYPE_CNT)
+#define        AUTHTYPE_NAME(x)        authtype_names[x]
+
+#define        ENCRYPT_IS              0
+#define        ENCRYPT_SUPPORT         1
+#define        ENCRYPT_REPLY           2
+#define        ENCRYPT_START           3
+#define        ENCRYPT_END             4
+#define        ENCRYPT_REQSTART        5
+#define        ENCRYPT_REQEND          6
+#define        ENCRYPT_ENC_KEYID       7
+#define        ENCRYPT_DEC_KEYID       8
+#define        ENCRYPT_CNT             9
+
+#define        ENCTYPE_ANY             0
+#define        ENCTYPE_DES_CFB64       1
+#define        ENCTYPE_DES_OFB64       2
+#define        ENCTYPE_CNT             3
+
+#ifdef ENCRYPT_NAMES
+char *encrypt_names[] = {
+       "IS", "SUPPORT", "REPLY", "START", "END",
+       "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
+       0,
+};
+char *enctype_names[] = {
+       "ANY", "DES_CFB64",  "DES_OFB64",  0,
+};
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
+#endif
+
+
+#define        ENCRYPT_NAME_OK(x)      ((unsigned int)(x) < ENCRYPT_CNT)
+#define        ENCRYPT_NAME(x)         encrypt_names[x]
+
+#define        ENCTYPE_NAME_OK(x)      ((unsigned int)(x) < ENCTYPE_CNT)
+#define        ENCTYPE_NAME(x)         enctype_names[x]
+
+#endif
diff --git a/include/assert.h b/include/assert.h
new file mode 100644 (file)
index 0000000..bad2ccd
--- /dev/null
@@ -0,0 +1,17 @@
+#undef assert
+
+#ifdef NDEBUG
+#define        assert(x) (void)0
+#else
+#define assert(x) ((x) || (__assert_fail(#x, __FILE__, __LINE__, __func__),0))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __assert_fail (const char *, const char *, int, const char *);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/bits/alltypes.h.sh b/include/bits/alltypes.h.sh
new file mode 100755 (executable)
index 0000000..595bf13
--- /dev/null
@@ -0,0 +1,115 @@
+#!/bin/sh
+sed -e << EOF \
+'/^TYPEDEF/s/TYPEDEF \(.*\) \([^ ]*\);$/#if defined(__NEED_\2) \&\& !defined(__DEFINED_\2)\
+typedef \1 \2;\
+#define __DEFINED_\2\
+#endif\
+/
+/^STRUCT/s/STRUCT * \([^ ]*\) \(.*\);$/#if defined(__NEED_struct_\1) \&\& !defined(__DEFINED_struct_\1)\
+struct \1 \2;\
+#define __DEFINED_struct_\1\
+#endif\
+/
+/^UNION/s/UNION * \([^ ]*\) \(.*\);$/#if defined(__NEED_union_\1) \&\& !defined(__DEFINED_union_\1)\
+union \1 \2;\
+#define __DEFINED_union_\1\
+#endif\
+/'
+
+TYPEDEF unsigned size_t;
+TYPEDEF int ssize_t;
+TYPEDEF long ptrdiff_t;
+TYPEDEF struct __va_list * va_list;
+
+TYPEDEF long wchar_t;
+TYPEDEF long wint_t;
+TYPEDEF long wctrans_t;
+TYPEDEF long wctype_t;
+
+TYPEDEF char      int8_t;
+TYPEDEF short     int16_t;
+TYPEDEF int       int32_t;
+TYPEDEF long long int64_t;
+
+TYPEDEF unsigned char      uint8_t;
+TYPEDEF unsigned short     uint16_t;
+TYPEDEF unsigned int       uint32_t;
+TYPEDEF unsigned long long uint64_t;
+
+TYPEDEF unsigned char      __uint8_t;
+TYPEDEF unsigned short     __uint16_t;
+TYPEDEF unsigned int       __uint32_t;
+TYPEDEF unsigned long long __uint64_t;
+
+TYPEDEF int8_t  int_least8_t;
+TYPEDEF int16_t int_least16_t;
+TYPEDEF int32_t int_least32_t;
+TYPEDEF int64_t int_least64_t;
+
+TYPEDEF uint8_t  uint_least8_t;
+TYPEDEF uint16_t uint_least16_t;
+TYPEDEF uint32_t uint_least32_t;
+TYPEDEF uint64_t uint_least64_t;
+
+TYPEDEF int8_t    int_fast8_t;
+TYPEDEF int       int_fast16_t;
+TYPEDEF int       int_fast32_t;
+TYPEDEF int64_t   int_fast64_t;
+
+TYPEDEF unsigned char      uint_fast8_t;
+TYPEDEF unsigned int       uint_fast16_t;
+TYPEDEF unsigned int       uint_fast32_t;
+TYPEDEF uint64_t           uint_fast64_t;
+
+TYPEDEF long          intptr_t;
+TYPEDEF unsigned long uintptr_t;
+
+TYPEDEF long long          intmax_t;
+TYPEDEF unsigned long long uintmax_t;
+
+TYPEDEF long time_t;
+TYPEDEF unsigned int useconds_t;
+TYPEDEF int suseconds_t;
+STRUCT timeval { time_t tv_sec; long tv_usec; };
+STRUCT timespec { time_t tv_sec; long tv_nsec; };
+
+TYPEDEF int pid_t;
+TYPEDEF int id_t;
+TYPEDEF int uid_t;
+TYPEDEF int gid_t;
+TYPEDEF int key_t;
+TYPEDEF struct __pthread * pthread_t;
+
+TYPEDEF long long off_t;
+
+TYPEDEF unsigned int mode_t;
+
+TYPEDEF unsigned int nlink_t;
+TYPEDEF unsigned long long ino_t;
+TYPEDEF long long dev_t;
+TYPEDEF long blksize_t;
+TYPEDEF long long blkcnt_t;
+TYPEDEF unsigned long long fsblkcnt_t;
+TYPEDEF unsigned long long fsfilcnt_t;
+
+TYPEDEF int timer_t;
+TYPEDEF int clockid_t;
+TYPEDEF unsigned long clock_t;
+
+TYPEDEF struct { unsigned long __bits[1024/sizeof(long)]; } sigset_t;
+TYPEDEF struct __siginfo siginfo_t;
+
+TYPEDEF unsigned int socklen_t;
+TYPEDEF unsigned short sa_family_t;
+TYPEDEF unsigned short in_port_t;
+TYPEDEF unsigned int in_addr_t;
+STRUCT in_addr { in_addr_t s_addr; };
+
+TYPEDEF struct __FILE_s FILE;
+
+TYPEDEF int nl_item;
+
+TYPEDEF struct __locale * locale_t;
+
+
+EOF
diff --git a/include/bits/endian.h b/include/bits/endian.h
new file mode 100644 (file)
index 0000000..172c338
--- /dev/null
@@ -0,0 +1 @@
+#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/include/bits/errno.h b/include/bits/errno.h
new file mode 100644 (file)
index 0000000..fddea5e
--- /dev/null
@@ -0,0 +1,125 @@
+#define EPERM            1
+#define ENOENT           2
+#define ESRCH            3
+#define EINTR            4
+#define EIO              5
+#define ENXIO            6
+#define E2BIG            7
+#define ENOEXEC          8
+#define EBADF            9
+#define ECHILD          10
+#define EAGAIN          11
+#define ENOMEM          12
+#define EACCES          13
+#define EFAULT          14
+#define ENOTBLK         15
+#define EBUSY           16
+#define EEXIST          17
+#define EXDEV           18
+#define ENODEV          19
+#define ENOTDIR         20
+#define EISDIR          21
+#define EINVAL          22
+#define ENFILE          23
+#define EMFILE          24
+#define ENOTTY          25
+#define ETXTBSY         26
+#define EFBIG           27
+#define ENOSPC          28
+#define ESPIPE          29
+#define EROFS           30
+#define EMLINK          31
+#define EPIPE           32
+#define EDOM            33
+#define ERANGE          34
+#define EDEADLK         35
+#define ENAMETOOLONG    36
+#define ENOLCK          37
+#define ENOSYS          38
+#define ENOTEMPTY       39
+#define ELOOP           40
+#define EWOULDBLOCK     EAGAIN
+#define ENOMSG          42
+#define EIDRM           43
+#define ECHRNG          44
+#define EL2NSYNC        45
+#define EL3HLT          46
+#define EL3RST          47
+#define ELNRNG          48
+#define EUNATCH         49
+#define ENOCSI          50
+#define EL2HLT          51
+#define EBADE           52
+#define EBADR           53
+#define EXFULL          54
+#define ENOANO          55
+#define EBADRQC         56
+#define EBADSLT         57
+#define EDEADLOCK       EDEADLK
+#define EBFONT          59
+#define ENOSTR          60
+#define ENODATA         61
+#define ETIME           62
+#define ENOSR           63
+#define ENONET          64
+#define ENOPKG          65
+#define EREMOTE         66
+#define ENOLINK         67
+#define EADV            68
+#define ESRMNT          69
+#define ECOMM           70
+#define EPROTO          71
+#define EMULTIHOP       72
+#define EDOTDOT         73
+#define EBADMSG         74
+#define EOVERFLOW       75
+#define ENOTUNIQ        76
+#define EBADFD          77
+#define EREMCHG         78
+#define ELIBACC         79
+#define ELIBBAD         80
+#define ELIBSCN         81
+#define ELIBMAX         82
+#define ELIBEXEC        83
+#define EILSEQ          84
+#define ERESTART        85
+#define ESTRPIPE        86
+#define EUSERS          87
+#define ENOTSOCK        88
+#define EDESTADDRREQ    89
+#define EMSGSIZE        90
+#define EPROTOTYPE      91
+#define ENOPROTOOPT     92
+#define EPROTONOSUPPORT 93
+#define ESOCKTNOSUPPORT 94
+#define EOPNOTSUPP      95
+#define EPFNOSUPPORT    96
+#define EAFNOSUPPORT    97
+#define EADDRINUSE      98
+#define EADDRNOTAVAIL   99
+#define ENETDOWN        100
+#define ENETUNREACH     101
+#define ENETRESET       102
+#define ECONNABORTED    103
+#define ECONNRESET      104
+#define ENOBUFS         105
+#define EISCONN         106
+#define ENOTCONN        107
+#define ESHUTDOWN       108
+#define ETOOMANYREFS    109
+#define ETIMEDOUT       110
+#define ECONNREFUSED    111
+#define EHOSTDOWN       112
+#define EHOSTUNREACH    113
+#define EALREADY        114
+#define EINPROGRESS     115
+#define ESTALE          116
+#define EUCLEAN         117
+#define ENOTNAM         118
+#define ENAVAIL         119
+#define EISNAM          120
+#define EREMOTEIO       121
+#define EDQUOT          122
+#define ENOMEDIUM       123
+#define EMEDIUMTYPE     124
+#define ECANCELED       125
diff --git a/include/bits/fcntl.h b/include/bits/fcntl.h
new file mode 100644 (file)
index 0000000..550152f
--- /dev/null
@@ -0,0 +1,59 @@
+#define O_ACCMODE 03
+#define O_RDONLY  00
+#define O_WRONLY  01
+#define O_RDWR    02
+
+#define O_CREAT        0100
+#define O_EXCL         0200
+#define O_NOCTTY       0400
+#define O_TRUNC       01000
+#define O_APPEND      02000
+#define O_NONBLOCK    04000
+#define O_SYNC       010000
+#define O_DIRECTORY 0200000
+#define O_NOFOLLOW  0400000
+#define O_CLOEXEC  02000000
+
+#ifdef _GNU_SOURCE
+#define O_ASYNC      020000
+#define O_DIRECT     040000
+#define O_NOATIME  01000000
+#define F_DUPFD_CLOEXEC 1030
+#define FAPPENT O_APPEND
+#define FFSYNC O_FSYNC
+#define FASYNC O_ASYNC
+#define FNONBLOCK O_NONBLOCK
+#define FNDELAY O_NDELAY
+#endif
+
+#define F_DUPFD  0
+#define F_GETFD  1
+#define F_SETFD  2
+#define F_GETFL  3
+#define F_SETFL  4
+
+#define F_SETOWN 8
+#define F_GETOWN 9
+
+#define F_GETLK 12
+#define F_SETLK 13
+#define F_SETLKW 14
+
+#define FD_CLOEXEC 1
+
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+#define AT_FDCWD (-100)
+#define AT_SYMLINK_NOFOLLOW 0x100
+#define AT_REMOVEDIR 0x200
+#define AT_SYMLINK_FOLLOW 0x400
+#define AT_EACCESS 0x200
+
+#define POSIX_FADV_NORMAL     0
+#define POSIX_FADV_RANDOM     1
+#define POSIX_FADV_SEQUENTIAL 2
+#define POSIX_FADV_WILLNEED   3
+#define POSIX_FADV_DONTNEED   4
+#define POSIX_FADV_NOREUSE    5
diff --git a/include/bits/fenv.h b/include/bits/fenv.h
new file mode 100644 (file)
index 0000000..24df041
--- /dev/null
@@ -0,0 +1,34 @@
+#define FE_INVALID    1
+#define __FE_DENORM   2
+#define FE_DIVBYZERO  4
+#define FE_OVERFLOW   8
+#define FE_UNDERFLOW  16
+#define FE_INEXACT    32
+
+#define FE_ALL_EXCEPT 63
+
+#define FE_TONEAREST  0
+#define FE_DOWNWARD   0x400
+#define FE_UPWARD     0x800
+#define FE_TOWARDZERO 0xc00
+
+typedef unsigned short fexcept_t;
+
+typedef struct {
+       unsigned short __control_word;
+       unsigned short __unused1;
+       unsigned short __status_word;
+       unsigned short __unused2;
+       unsigned short __tags;
+       unsigned short __unused3;
+       unsigned int __eip;
+       unsigned short __cs_selector;
+       unsigned int __opcode:11;
+       unsigned int __unused4:5;
+       unsigned int __data_offset;
+       unsigned short __data_selector;
+       unsigned short __unused5;
+       unsigned int __mxcsr;
+} fenv_t;
+
+#define FE_DFL_ENV      ((const fenv_t *) -1)
diff --git a/include/bits/float.h b/include/bits/float.h
new file mode 100644 (file)
index 0000000..162b3e4
--- /dev/null
@@ -0,0 +1,11 @@
+#define LDBL_MIN     3.3621031431120935063e-4932L
+#define LDBL_MAX     1.1897314953572317650e+4932L
+#define LDBL_EPSILON 1.0842021724855044340e-19L
+
+#define LDBL_MANT_DIG 64
+#define LDBL_MIN_EXP (-16381)
+#define LDBL_MAX_EXP 16384
+
+#define LDBL_DIG 18
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
diff --git a/include/bits/in.h b/include/bits/in.h
new file mode 100644 (file)
index 0000000..53ca31c
--- /dev/null
@@ -0,0 +1,89 @@
+#define IP_TOS             1
+#define IP_TTL             2
+#define IP_HDRINCL         3
+#define IP_OPTIONS         4
+#define IP_ROUTER_ALERT    5
+#define IP_RECVOPTS        6
+#define IP_RETOPTS         7
+//#define IP_PKTINFO         8
+#define IP_PKTOPTIONS      9
+#define IP_PMTUDISC        10
+#define IP_MTU_DISCOVER    10
+#define IP_RECVERR         11
+#define IP_RECVTTL         12
+#define IP_RECVTOS         13
+#define IP_MULTICAST_IF    32
+#define IP_MULTICAST_TTL   33
+#define IP_MULTICAST_LOOP  34
+#define IP_ADD_MEMBERSHIP  35
+#define IP_DROP_MEMBERSHIP 36
+
+#define IP_RECVRETOPTS IP_RETOPTS
+
+#define IP_PMTUDISC_DONT   0
+#define IP_PMTUDISC_WANT   1
+#define IP_PMTUDISC_DO     2
+
+#define SOL_IP 0
+
+#define IP_DEFAULT_MULTICAST_TTL        1
+#define IP_DEFAULT_MULTICAST_LOOP       1
+#define IP_MAX_MEMBERSHIPS              20
+
+struct ip_opts
+{
+       struct in_addr ip_dst;
+       char ip_opts[40];
+};
+
+struct ip_mreq
+{
+       struct in_addr imr_multiaddr;
+       struct in_addr imr_interface;
+};
+
+struct ip_mreqn
+{
+       struct in_addr imr_multiaddr;
+       struct in_addr imr_address;
+       int imr_ifindex;
+};
+
+struct in_pktinfo
+{
+       int ipi_ifindex;
+       struct in_addr ipi_spec_dst;
+       struct in_addr ipi_addr;
+};
+
+#define IPV6_ADDRFORM           1
+#define IPV6_PKTINFO            2
+#define IPV6_HOPOPTS            3
+#define IPV6_DSTOPTS            4
+#define IPV6_RXSRCRT            5
+#define IPV6_PKTOPTIONS         6
+#define IPV6_CHECKSUM           7
+#define IPV6_HOPLIMIT           8
+#define IPV6_NEXTHOP            9
+#define IPV6_AUTHHDR            10
+#define IPV6_UNICAST_HOPS       16
+#define IPV6_MULTICAST_IF       17
+#define IPV6_MULTICAST_HOPS     18
+#define IPV6_MULTICAST_LOOP     19
+#define IPV6_ADD_MEMBERSHIP     20
+#define IPV6_DROP_MEMBERSHIP    21
+#define IPV6_ROUTER_ALERT       22
+
+#define SCM_SRCRT               IPV6_RXSRCRT
+
+#define IPV6_RXHOPOPTS          IPV6_HOPOPTS
+#define IPV6_RXDSTOPTS          IPV6_DSTOPTS
+
+
+#define IPV6_PMTUDISC_DONT      0
+#define IPV6_PMTUDISC_WANT      1
+#define IPV6_PMTUDISC_DO        2
+
+
+#define SOL_IPV6        41
+#define SOL_ICMPV6      58
diff --git a/include/bits/ioctl.h b/include/bits/ioctl.h
new file mode 100644 (file)
index 0000000..bb63ffb
--- /dev/null
@@ -0,0 +1,182 @@
+#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) )
+#define _IOC_NONE  0U
+#define _IOC_WRITE 1U
+#define _IOC_READ  2U
+
+#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0)
+#define _IOW(a,b,c) _IOC(1,(a),(b),sizeof(c))
+#define _IOR(a,b,c) _IOC(2,(a),(b),sizeof(c))
+#define _IOWR(a,b,c) _IOC(3,(a),(b),sizeof(c))
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402
+#define TCSETSW                0x5403
+#define TCSETSF                0x5404
+#define TCGETA         0x5405
+#define TCSETA         0x5406
+#define TCSETAW                0x5407
+#define TCSETAF                0x5408
+#define TCSBRK         0x5409
+#define TCXONC         0x540A
+#define TCFLSH         0x540B
+#define TIOCEXCL       0x540C
+#define TIOCNXCL       0x540D
+#define TIOCSCTTY      0x540E
+#define TIOCGPGRP      0x540F
+#define TIOCSPGRP      0x5410
+#define TIOCOUTQ       0x5411
+#define TIOCSTI                0x5412
+#define TIOCGWINSZ     0x5413
+#define TIOCSWINSZ     0x5414
+#define TIOCMGET       0x5415
+#define TIOCMBIS       0x5416
+#define TIOCMBIC       0x5417
+#define TIOCMSET       0x5418
+#define TIOCGSOFTCAR   0x5419
+#define TIOCSSOFTCAR   0x541A
+#define FIONREAD       0x541B
+#define TIOCINQ                FIONREAD
+#define TIOCLINUX      0x541C
+#define TIOCCONS       0x541D
+#define TIOCGSERIAL    0x541E
+#define TIOCSSERIAL    0x541F
+#define TIOCPKT                0x5420
+#define FIONBIO                0x5421
+#define TIOCNOTTY      0x5422
+#define TIOCSETD       0x5423
+#define TIOCGETD       0x5424
+#define TCSBRKP                0x5425
+#define TIOCTTYGSTRUCT 0x5426
+#define TIOCSBRK       0x5427
+#define TIOCCBRK       0x5428
+#define TIOCGSID       0x5429
+#define TIOCGPTN       0x80045430
+#define TIOCSPTLCK     0x40045431
+
+#define FIONCLEX       0x5450
+#define FIOCLEX                0x5451
+#define FIOASYNC       0x5452
+#define TIOCSERCONFIG  0x5453
+#define TIOCSERGWILD   0x5454
+#define TIOCSERSWILD   0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458
+#define TIOCSERGETLSR   0x5459
+#define TIOCSERGETMULTI 0x545A
+#define TIOCSERSETMULTI 0x545B
+
+#define TIOCMIWAIT     0x545C
+#define TIOCGICOUNT    0x545D
+#define TIOCGHAYESESP   0x545E
+#define TIOCSHAYESESP   0x545F
+#define FIOQSIZE       0x5460
+
+#define TIOCPKT_DATA            0
+#define TIOCPKT_FLUSHREAD       1
+#define TIOCPKT_FLUSHWRITE      2
+#define TIOCPKT_STOP            4
+#define TIOCPKT_START           8
+#define TIOCPKT_NOSTOP         16
+#define TIOCPKT_DOSTOP         32
+
+#define TIOCSER_TEMT    0x01
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define TIOCM_LE        0x001
+#define TIOCM_DTR       0x002
+#define TIOCM_RTS       0x004
+#define TIOCM_ST        0x008
+#define TIOCM_SR        0x010
+#define TIOCM_CTS       0x020
+#define TIOCM_CAR       0x040
+#define TIOCM_RNG       0x080
+#define TIOCM_DSR       0x100
+#define TIOCM_CD        TIOCM_CAR
+#define TIOCM_RI        TIOCM_RNG
+#define TIOCM_OUT1      0x2000
+#define TIOCM_OUT2      0x4000
+#define TIOCM_LOOP      0x8000
+#define TIOCM_MODEM_BITS TIOCM_OUT2
+
+#define N_TTY           0
+#define N_SLIP          1
+#define N_MOUSE         2
+#define N_PPP           3
+#define N_STRIP         4
+#define N_AX25          5
+#define N_X25           6
+#define N_6PACK         7
+#define N_MASC          8
+#define N_R3964         9
+#define N_PROFIBUS_FDL  10
+#define N_IRDA          11
+#define N_SMSBLOCK      12
+#define N_HDLC          13
+#define N_SYNC_PPP      14
+#define N_HCI           15
+
+#define SIOCADDRT       0x890B
+#define SIOCDELRT       0x890C
+#define SIOCRTMSG       0x890D
+
+#define SIOCGIFNAME     0x8910
+#define SIOCSIFLINK     0x8911
+#define SIOCGIFCONF     0x8912
+#define SIOCGIFFLAGS    0x8913
+#define SIOCSIFFLAGS    0x8914
+#define SIOCGIFADDR     0x8915
+#define SIOCSIFADDR     0x8916
+#define SIOCGIFDSTADDR  0x8917
+#define SIOCSIFDSTADDR  0x8918
+#define SIOCGIFBRDADDR  0x8919
+#define SIOCSIFBRDADDR  0x891a
+#define SIOCGIFNETMASK  0x891b
+#define SIOCSIFNETMASK  0x891c
+#define SIOCGIFMETRIC   0x891d
+#define SIOCSIFMETRIC   0x891e
+#define SIOCGIFMEM      0x891f
+#define SIOCSIFMEM      0x8920
+#define SIOCGIFMTU      0x8921
+#define SIOCSIFMTU      0x8922
+#define SIOCSIFHWADDR   0x8924
+#define SIOCGIFENCAP    0x8925
+#define SIOCSIFENCAP    0x8926
+#define SIOCGIFHWADDR   0x8927
+#define SIOCGIFSLAVE    0x8929
+#define SIOCSIFSLAVE    0x8930
+#define SIOCADDMULTI    0x8931
+#define SIOCDELMULTI    0x8932
+#define SIOCGIFINDEX    0x8933
+#define SIOGIFINDEX     SIOCGIFINDEX
+#define SIOCSIFPFLAGS   0x8934
+#define SIOCGIFPFLAGS   0x8935
+#define SIOCDIFADDR     0x8936
+#define SIOCSIFHWBROADCAST 0x8937
+#define SIOCGIFCOUNT    0x8938
+
+#define SIOCGIFBR       0x8940
+#define SIOCSIFBR       0x8941
+
+#define SIOCGIFTXQLEN   0x8942
+#define SIOCSIFTXQLEN   0x8943
+
+#define SIOCDARP        0x8953
+#define SIOCGARP        0x8954
+#define SIOCSARP        0x8955
+
+#define SIOCDRARP       0x8960
+#define SIOCGRARP       0x8961
+#define SIOCSRARP       0x8962
+
+#define SIOCGIFMAP      0x8970
+#define SIOCSIFMAP      0x8971
+
+#define SIOCADDDLCI     0x8980
+#define SIOCDELDLCI     0x8981
diff --git a/include/bits/ipc.h b/include/bits/ipc.h
new file mode 100644 (file)
index 0000000..8e3ef9b
--- /dev/null
@@ -0,0 +1,22 @@
+#define IPC_CREAT  01000
+#define IPC_EXCL   02000
+#define IPC_NOWAIT 04000
+
+#define IPC_RMID 0
+#define IPC_SET  1
+#define IPC_STAT 2
+
+#define IPC_PRIVATE ((key_t) 0)
+
+struct ipc_perm
+{
+       key_t key;
+       uid_t uid;
+       gid_t gid;
+       uid_t cuid;
+       gid_t cgid;
+       mode_t mode;
+       int seq;
+       long __pad1;
+       long __pad2;
+};
diff --git a/include/bits/limits.h b/include/bits/limits.h
new file mode 100644 (file)
index 0000000..48fdd7a
--- /dev/null
@@ -0,0 +1,32 @@
+#define PIPE_BUF 4096
+#define PAGESIZE 4096
+#define PAGE_SIZE PAGESIZE
+#define FILESIZEBITS 64
+#define NAME_MAX 255
+#define SYMLINK_MAX 255
+#define PATH_MAX 4096
+#define NZERO 20
+#define NGROUPS_MAX 32
+#define ARG_MAX 131072
+#define IOV_MAX 1024
+#define SYMLOOP_MAX 40
+
+#define WORD_BIT 32
+#define LONG_BIT 32
+
+#define SHRT_MIN  (-1-0x7fff)
+#define SHRT_MAX  0x7fff
+#define USHRT_MAX 0xffff
+
+#define INT_MIN  (-1-0x7fffffff)
+#define INT_MAX  0x7fffffff
+#define UINT_MAX 0xffffffff
+
+#define LONG_MIN  (-1-0x7fffffffL)
+#define LONG_MAX  0x7fffffffL
+#define ULONG_MAX 0xffffffffL
+
+#define LLONG_MIN  (-1-0x7fffffffffffffffLL)
+#define LLONG_MAX  0x7fffffffffffffffLL
+#define ULLONG_MAX 0xffffffffffffffffULL
+
diff --git a/include/bits/mman.h b/include/bits/mman.h
new file mode 100644 (file)
index 0000000..e02d488
--- /dev/null
@@ -0,0 +1,39 @@
+#define MAP_FAILED ((void *) -1)
+
+#define        PROT_NONE      0
+#define        PROT_READ      1
+#define        PROT_WRITE     2
+#define        PROT_EXEC      4
+
+#define        MAP_SHARED     0x01
+#define        MAP_PRIVATE    0x02
+#define        MAP_FIXED      0x10
+
+/* linux extensions */
+#define MAP_TYPE       0x0f
+#define MAP_FILE       0x00
+#define MAP_ANON       0x20
+#define MAP_ANONYMOUS  MAP_ANON
+
+#define MADV_NORMAL     0
+#define MADV_RANDOM     1
+#define MADV_SEQUENTIAL 2
+#define MADV_WILLNEED   3
+#define MADV_DONTNEED   4
+
+#define POSIX_MADV_NORMAL       0
+#define POSIX_MADV_RANDOM       1
+#define POSIX_MADV_SEQUENTIAL   2
+#define POSIX_MADV_WILLNEED     3
+#define POSIX_MADV_DONTNEED     0
+
+#define MS_ASYNC        1
+#define MS_INVALIDATE   2
+#define MS_SYNC         4
+
+#define MCL_CURRENT     1
+#define MCL_FUTURE      2
+
+/* linux extensions */
+#define MREMAP_MAYMOVE  1
+#define MREMAP_FIXED    2
diff --git a/include/bits/posix.h b/include/bits/posix.h
new file mode 100644 (file)
index 0000000..30a3871
--- /dev/null
@@ -0,0 +1,2 @@
+#define _POSIX_V6_ILP32_OFFBIG  1
+#define _POSIX_V7_ILP32_OFFBIG  1
diff --git a/include/bits/pthread.h b/include/bits/pthread.h
new file mode 100644 (file)
index 0000000..7d19065
--- /dev/null
@@ -0,0 +1,6 @@
+struct __ptcb {
+       long __jb[7];
+       int __dummy;
+       struct __ptcb *__next;
+       void *__ptrs[3];
+};
diff --git a/include/bits/reg.h b/include/bits/reg.h
new file mode 100644 (file)
index 0000000..8bc2582
--- /dev/null
@@ -0,0 +1,19 @@
+#undef __WORDSIZE
+#define __WORDSIZE 32
+#define EBX 0
+#define ECX 1
+#define EDX 2
+#define ESI 3
+#define EDI 4
+#define EBP 5
+#define EAX 6
+#define DS 7
+#define ES 8
+#define FS 9
+#define GS 10
+#define ORIG_EAX 11
+#define EIP 12
+#define CS 13
+#define EFL 14
+#define UESP 15
+#define SS 16
diff --git a/include/bits/setjmp.h b/include/bits/setjmp.h
new file mode 100644 (file)
index 0000000..b6595bd
--- /dev/null
@@ -0,0 +1 @@
+typedef unsigned long jmp_buf [7];
diff --git a/include/bits/shm.h b/include/bits/shm.h
new file mode 100644 (file)
index 0000000..4677423
--- /dev/null
@@ -0,0 +1,18 @@
+#define SHMLBA 4096
+
+#define SHM_RDONLY 010000
+#define SHM_RND    020000
+
+struct shmid_ds
+{
+       struct ipc_perm shm_perm;
+       size_t shm_segsz;
+       time_t shm_atime;
+       time_t shm_dtime;
+       time_t shm_ctime;
+       pid_t shm_cpid;
+       pid_t shm_lpid;
+       unsigned long shm_nattch;
+       unsigned long __pad1;
+       unsigned long __pad2;
+};
diff --git a/include/bits/signal.h b/include/bits/signal.h
new file mode 100644 (file)
index 0000000..2427f37
--- /dev/null
@@ -0,0 +1,98 @@
+struct __siginfo
+{
+       int si_signo;
+       int si_errno;
+       int si_code;
+       union
+       {
+               char __pad[128 - 3*sizeof(int)];
+               struct {
+                       pid_t si_pid;
+                       uid_t si_uid;
+                       union sigval si_sigval;
+               } __rt;
+               struct {
+                       unsigned int si_timer1;
+                       unsigned int si_timer2;
+               } __timer;
+               struct {
+                       pid_t si_pid;
+                       uid_t si_uid;
+                       int si_status;
+                       clock_t si_utime;
+                       clock_t si_stime;
+               } __sigchld;
+               struct {
+                       void *si_addr;
+               } __sigfault;
+               struct {
+                       long int si_band;
+                       int si_fd;
+               } __sigpoll;
+       } __si_fields;
+};
+
+#define si_pid     __si_fields.__sigchld.si_pid
+#define si_uid     __si_fields.__sigchld.si_uid
+#define si_status  __si_fields.__sigchld.si_status
+#define si_utime   __si_fields.__sigchld.si_utime
+#define si_stime   __si_fields.__sigchld.si_stime
+#define si_value   __si_fields.__rt.si_sigval
+#define si_addr    __si_fields.__sigfault.si_addr
+#define si_band    __si_fields.__sigpoll.si_band
+
+#define SA_NOCLDSTOP  1
+#define SA_NOCLDWAIT  2
+#define SA_SIGINFO    4
+#define SA_ONSTACK    0x08000000
+#define SA_RESTART    0x10000000
+#define SA_NODEFER    0x40000000
+#define SA_RESETHAND  0x80000000
+
+#define SS_ONSTACK    1
+#define SS_DISABLE    2
+
+#define SIG_BLOCK     0
+#define SIG_UNBLOCK   1
+#define SIG_SETMASK   2
+
+#define SIG_ERR  ((void (*)(int))-1)
+#define SIG_DFL  ((void (*)(int)) 0)
+#define SIG_IGN  ((void (*)(int)) 1)
+#define SIG_HOLD ((void (*)(int)) 2)
+
+#define NSIG      64
+
+#define SIGHUP    1
+#define SIGINT    2
+#define SIGQUIT   3
+#define SIGILL    4
+#define SIGTRAP   5
+#define SIGABRT   6
+#define SIGBUS    7
+#define SIGFPE    8
+#define SIGKILL   9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   29
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
diff --git a/include/bits/socket.h b/include/bits/socket.h
new file mode 100644 (file)
index 0000000..7a51f79
--- /dev/null
@@ -0,0 +1,189 @@
+struct iovec;
+
+struct msghdr
+{
+       void *msg_name;
+       socklen_t msg_namelen;
+       struct iovec *msg_iov;
+       int msg_iovlen;
+       void *msg_control;
+       socklen_t msg_controllen;
+       int msg_flags;
+};
+
+struct cmsghdr
+{
+       socklen_t cmsg_len;
+       int cmsg_level;
+       int cmsg_type;
+};
+
+struct ucred
+{
+       pid_t pid;
+       uid_t uid;
+       gid_t gid;
+};
+
+struct linger
+{
+       int l_onoff;
+       int l_linger;
+};
+
+#define SHUT_RD 0
+#define SHUT_WD 1
+#define SHUT_RDWR 2
+
+#define SOCK_STREAM    1
+#define SOCK_DGRAM     2
+#define SOCK_RAW       3
+#define SOCK_RDM       4
+#define SOCK_SEQPACKET 5
+#define SOCK_PACKET    10
+
+#define AF_UNSPEC       0
+#define AF_LOCAL        1
+#define AF_UNIX         AF_LOCAL
+#define AF_FILE         AF_LOCAL
+#define AF_INET         2
+#define AF_AX25         3
+#define AF_IPX          4
+#define AF_APPLETALK    5
+#define AF_NETROM       6
+#define AF_BRIDGE       7
+#define AF_ATMPVC       8
+#define AF_X25          9
+#define AF_INET6        10
+#define AF_ROSE         11
+#define AF_DECnet       12
+#define AF_NETBEUI      13
+#define AF_SECURITY     14
+#define AF_KEY          15
+#define AF_NETLINK      16
+#define AF_ROUTE        AF_NETLINK
+#define AF_PACKET       17
+#define AF_ASH          18
+#define AF_ECONET       19
+#define AF_ATMSVC       20
+#define AF_SNA          22
+#define AF_IRDA         23
+#define AF_PPPOX        24
+#define AF_WANPIPE      25
+#define AF_BLUETOOTH    31
+
+#define PF_UNSPEC       0
+#define PF_LOCAL        1
+#define PF_UNIX         PF_LOCAL
+#define PF_FILE         PF_LOCAL
+#define PF_INET         2
+#define PF_AX25         3
+#define PF_IPX          4
+#define PF_APPLETALK    5
+#define PF_NETROM       6
+#define PF_BRIDGE       7
+#define PF_ATMPVC       8
+#define PF_X25          9
+#define PF_INET6        10
+#define PF_ROSE         11
+#define PF_DECnet       12
+#define PF_NETBEUI      13
+#define PF_SECURITY     14
+#define PF_KEY          15
+#define PF_NETLINK      16
+#define PF_ROUTE        PF_NETLINK
+#define PF_PACKET       17
+#define PF_ASH          18
+#define PF_ECONET       19
+#define PF_ATMSVC       20
+#define PF_SNA          22
+#define PF_IRDA         23
+#define PF_PPPOX        24
+#define PF_WANPIPE      25
+#define PF_BLUETOOTH    31
+
+#define SO_DEBUG        1
+#define SO_REUSEADDR    2
+#define SO_TYPE         3
+#define SO_ERROR        4
+#define SO_DONTROUTE    5
+#define SO_BROADCAST    6
+#define SO_SNDBUF       7
+#define SO_RCVBUF       8
+#define SO_KEEPALIVE    9
+#define SO_OOBINLINE    10
+#define SO_NO_CHECK     11
+#define SO_PRIORITY     12
+#define SO_LINGER       13
+#define SO_BSDCOMPAT    14
+#define SO_REUSEPORT    15
+#define SO_PASSCRED     16
+#define SO_PEERCRED     17
+#define SO_RCVLOWAT     18
+#define SO_SNDLOWAT     19
+#define SO_RCVTIMEO     20
+#define SO_SNDTIMEO     21
+
+#define SO_SECURITY_AUTHENTICATION              22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT        23
+#define SO_SECURITY_ENCRYPTION_NETWORK          24
+
+#define SO_BINDTODEVICE 25
+
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME             28
+#define SO_TIMESTAMP            29
+#define SCM_TIMESTAMP           SO_TIMESTAMP
+
+#define SO_ACCEPTCONN           30
+
+#define SOL_SOCKET      1
+
+/* ??? */
+#define SOL_RAW         255
+#define SOL_DECNET      261
+#define SOL_X25         262
+#define SOL_PACKET      263
+#define SOL_ATM         264
+#define SOL_AAL         265
+#define SOL_IRDA        266
+
+#define SOMAXCONN       128
+
+#define MSG_OOB       0x0001
+#define MSG_PEEK      0x0002
+#define MSG_DONTROUTE 0x0004
+#define MSG_CTRUNC    0x0008
+#define MSG_PROXY     0x0010
+#define MSG_TRUNC     0x0020
+#define MSG_DONTWAIT  0x0040
+#define MSG_EOR       0x0080
+#define MSG_WAITALL   0x0100
+#define MSG_FIN       0x0200
+#define MSD_SYN       0x0400
+#define MSG_CONFIRM   0x0800
+#define MSG_RST       0x1000
+#define MSG_ERRQUEUE  0x2000
+#define MSG_NOSIGNAL  0x4000
+#define MSG_MORE      0x8000
+
+/* Internal use only!! to make CMSG_NXTHDR definition readable by mortals */
+#define __CMSG_LEN(cmsg) (((cmsg)->cmsg_len + sizeof(long) - 1) & ~(long)(sizeof(long) - 1))
+#define __CMSG_NEXT(cmsg) ((unsigned char *)(cmsg) + __CMSG_LEN(cmsg))
+#define __MHDR_END(mhdr) ((unsigned char *)(mhdr)->msg_control + (mhdr)->msg_controllen)
+
+#define CMSG_DATA(cmsg) ((unsigned char *) (((struct cmsghdr *)(cmsg)) + 1))
+#define CMSG_NXTHDR(mhdr, cmsg) ((cmsg)->cmsg_len < sizeof (struct cmsghdr) ? (struct cmsghdr *)0 : \
+        (__CMSG_NEXT(cmsg) + sizeof (struct cmsghdr) >= __MHDR_END(mhdr) ? (struct cmsghdr *)0 : \
+        ((struct cmsghdr *)__CMSG_NEXT(cmsg))))
+#define CMSG_FIRSTHDR(mhdr) ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) 0)
+
+/* Are these valid? */
+#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1))
+#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr)))
+#define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
+
+#define SCM_RIGHTS      0x01
+#define SCM_CREDENTIALS 0x02
diff --git a/include/bits/stat.h b/include/bits/stat.h
new file mode 100644 (file)
index 0000000..1ef3469
--- /dev/null
@@ -0,0 +1,25 @@
+/* copied from kernel definition, but with padding replaced
+ * by the corresponding correctly-sized userspace types. */
+
+struct stat
+{
+       dev_t st_dev;
+       int __st_dev_padding;
+       long __st_ino_truncated;
+       mode_t st_mode;
+       nlink_t st_nlink;
+       uid_t st_uid;
+       gid_t st_gid;
+       dev_t st_rdev;
+       int __st_rdev_padding;
+       off_t st_size;
+       blksize_t st_blksize;
+       blkcnt_t st_blocks;
+       time_t st_atime;
+       unsigned long __st_atime_nsec;
+       time_t st_mtime;
+       unsigned long __st_mtime_nsec;
+       time_t st_ctime;
+       unsigned long __st_ctime_nsec;
+       ino_t st_ino;
+};
diff --git a/include/bits/statfs.h b/include/bits/statfs.h
new file mode 100644 (file)
index 0000000..9dda440
--- /dev/null
@@ -0,0 +1,16 @@
+struct statvfs {
+       unsigned long f_type;
+       unsigned long f_bsize;
+       fsblkcnt_t f_blocks;
+       fsblkcnt_t f_bfree;
+       fsblkcnt_t f_bavail;
+       fsfilcnt_t f_files;
+       fsfilcnt_t f_ffree;
+       unsigned long f_fsid;
+       unsigned long __unused;
+       unsigned long f_namemax;
+       unsigned long f_frsize;
+       fsfilcnt_t f_favail;
+       unsigned long f_flag;
+       unsigned long __reserved[2];
+};
diff --git a/include/bits/stdint.h b/include/bits/stdint.h
new file mode 100644 (file)
index 0000000..8e21a8c
--- /dev/null
@@ -0,0 +1,23 @@
+#define INT_FAST8_MIN   INT8_MIN
+#define INT_FAST16_MIN  INT32_MIN
+#define INT_FAST32_MIN  INT32_MIN
+#define INT_FAST64_MIN  INT64_MIN
+
+#define INT_FAST8_MAX   INT8_MAX
+#define INT_FAST16_MAX  INT32_MAX
+#define INT_FAST32_MAX  INT32_MAX
+#define INT_FAST64_MAX  INT64_MAX
+
+#define UINT_FAST8_MAX  UINT8_MAX
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+#define INTPTR_MIN      INT32_MIN
+#define INTPTR_MAX      INT32_MAX
+#define UINTPTR_MAX     UINT32_MAX
+#define PTRDIFF_MIN     INT32_MIN
+#define PTRDIFF_MAX     INT32_MAX
+#define SIG_ATOMIC_MIN  INT32_MIN
+#define SIG_ATOMIC_MAX  INT32_MAX
+#define SIZE_MAX        UINT32_MAX
diff --git a/include/bits/stdio.h b/include/bits/stdio.h
new file mode 100644 (file)
index 0000000..0afd8b4
--- /dev/null
@@ -0,0 +1,10 @@
+#define BUFSIZ 1024
+
+#define FILENAME_MAX 4095
+#define FOPEN_MAX 1000
+#define TMP_MAX 10000
+
+#define L_cuserid 20
+#define L_ctermid 20
+#define L_tmpnam 20
+#define P_tmpdir "/tmp"
diff --git a/include/bits/sysmacros.h b/include/bits/sysmacros.h
new file mode 100644 (file)
index 0000000..da29022
--- /dev/null
@@ -0,0 +1,7 @@
+#define major(x) (((x) >> 8) & 0xff)
+#define minor(x) ((x) & 0xff)
+#define makedev(x,y) (((x)<<8)|((y)&0xff))
+
+//#define makedev(x,y) \
+//     ((x)*0x100000001ULL)&(0xfffffffffff0)
+//     ((y)*0x1001 & 0xffff0ff)
diff --git a/include/bits/tcp.h b/include/bits/tcp.h
new file mode 100644 (file)
index 0000000..923231b
--- /dev/null
@@ -0,0 +1 @@
+#define TCP_NODELAY 1
diff --git a/include/bits/termios.h b/include/bits/termios.h
new file mode 100644 (file)
index 0000000..316baeb
--- /dev/null
@@ -0,0 +1,158 @@
+struct termios
+{
+       tcflag_t c_iflag;
+       tcflag_t c_oflag;
+       tcflag_t c_cflag;
+       tcflag_t c_lflag;
+       cc_t c_line;
+       cc_t c_cc[NCCS];
+       speed_t __c_ispeed;
+       speed_t __c_ospeed;
+};
+
+#define VINTR     0
+#define VQUIT     1
+#define VERASE    2
+#define VKILL     3
+#define VEOF      4
+#define VTIME     5
+#define VMIN      6
+#define VSWTC     7
+#define VSTART    8
+#define VSTOP     9
+#define VSUSP    10
+#define VEOL     11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE  14
+#define VLNEXT   15
+#define VEOL2    16
+
+#define IGNBRK  0000001
+#define BRKINT  0000002
+#define IGNPAR  0000004
+#define PARMRK  0000010
+#define INPCK   0000020
+#define ISTRIP  0000040
+#define INLCR   0000100
+#define IGNCR   0000200
+#define ICRNL   0000400
+#define IUCLC   0001000
+#define IXON    0002000
+#define IXANY   0004000
+#define IXOFF   0010000
+#define IMAXBEL 0020000
+
+#define OPOST  0000001
+#define OLCUC  0000002
+#define ONLCR  0000004
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define NL0    0000000
+#define NL1    0000400
+#define CRDLY  0003000
+#define CR0    0000000
+#define CR1    0001000
+#define CR2    0002000
+#define CR3    0003000
+#define TABDLY 0014000
+#define TAB0   0000000
+#define TAB1   0004000
+#define TAB2   0010000
+#define TAB3   0014000
+#define BSDLY  0020000
+#define BS0    0000000
+#define BS1    0020000
+#define FFDLY  0100000
+#define FF0    0000000
+#define FF1    0100000
+
+#define VTDLY  0040000
+#define VT0    0000000
+#define VT1    0040000
+
+/* ?? */
+#define XTABS  0014000
+
+#define B0       0000000
+#define B50      0000001
+#define B75      0000002
+#define B110     0000003
+#define B134     0000004
+#define B150     0000005
+#define B200     0000006
+#define B300     0000007
+#define B600     0000010
+#define B1200    0000011
+#define B1800    0000012
+#define B2400    0000013
+#define B4800    0000014
+#define B9600    0000015
+#define B19200   0000016
+#define B38400   0000017
+
+#define B57600   0010001
+#define B115200  0010002
+#define B230400  0010003
+#define B460800  0010004
+#define B500000  0010005
+#define B576000  0010006
+#define B921600  0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+
+#define CBAUD    0010017
+
+#define CSIZE  0000060
+#define CS5    0000000
+#define CS6    0000020
+#define CS7    0000040
+#define CS8    0000060
+#define CSTOPB 0000100
+#define CREAD  0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL  0002000
+#define CLOCAL 0004000
+
+#define CRTSCTS  020000000000
+
+#define ISIG   0000001
+#define ICANON 0000002
+#define ECHO   0000010
+#define ECHOE  0000020
+#define ECHOK  0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define IEXTEN 0100000
+
+/* Extensions? */
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+
+#define TCOOFF 0
+#define TCOON  1
+#define TCIOFF 2
+#define TCION  3
+
+#define TCIFLUSH  0
+#define TCOFLUSH  1
+#define TCIOFLUSH 2
+
+#define TCSANOW   0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
diff --git a/include/bits/uio.h b/include/bits/uio.h
new file mode 100644 (file)
index 0000000..4325265
--- /dev/null
@@ -0,0 +1,4 @@
+struct iovec {
+       void *iov_base;
+       size_t iov_len;
+};
diff --git a/include/bits/user.h b/include/bits/user.h
new file mode 100644 (file)
index 0000000..13ff027
--- /dev/null
@@ -0,0 +1,77 @@
+#undef __WORDSIZE
+#define __WORDSIZE 32
+
+struct user_fpregs_struct
+{
+       long int cwd;
+       long int swd;
+       long int twd;
+       long int fip;
+       long int fcs;
+       long int foo;
+       long int fos;
+       long int st_space[20];
+};
+
+struct user_fpxregs_struct
+{
+       unsigned short int cwd;
+       unsigned short int swd;
+       unsigned short int twd;
+       unsigned short int fop;
+       long int fip;
+       long int fcs;
+       long int foo;
+       long int fos;
+       long int mxcsr;
+       long int reserved;
+       long int st_space[32];
+       long int xmm_space[32];
+       long int padding[56];
+};
+
+struct user_regs_struct
+{
+       long int ebx;
+       long int ecx;
+       long int edx;
+       long int esi;
+       long int edi;
+       long int ebp;
+       long int eax;
+       long int xds;
+       long int xes;
+       long int xfs;
+       long int xgs;
+       long int orig_eax;
+       long int eip;
+       long int xcs;
+       long int eflags;
+       long int esp;
+       long int xss;
+};
+
+struct user
+{
+       struct user_regs_struct         regs;
+       int                             u_fpvalid;
+       struct user_fpregs_struct       i387;
+       unsigned long int               u_tsize;
+       unsigned long int               u_dsize;
+       unsigned long int               u_ssize;
+       unsigned long                   start_code;
+       unsigned long                   start_stack;
+       long int                        signal;
+       int                             reserved;
+       struct user_regs_struct         *u_ar0;
+       struct user_fpregs_struct       *u_fpstate;
+       unsigned long int               magic;
+       char                            u_comm[32];
+       int                             u_debugreg[8];
+};
+
+#define PAGE_MASK              (~(PAGE_SIZE-1))
+#define NBPG                   PAGE_SIZE
+#define UPAGES                 1
+#define HOST_TEXT_START_ADDR   (u.start_code)
+#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
diff --git a/include/bits/wait.h b/include/bits/wait.h
new file mode 100644 (file)
index 0000000..ca9b57e
--- /dev/null
@@ -0,0 +1,11 @@
+#define WNOHANG    1
+#define WUNTRACED  2
+
+#define WSTOPPED   2
+#define WEXITED    4
+#define WCONTINUED 8
+#define WNOWAIT    0x1000000
+
+#define P_ALL  0
+#define P_PID  1
+#define P_PGID 2
diff --git a/include/bits/wexitstatus.h b/include/bits/wexitstatus.h
new file mode 100644 (file)
index 0000000..34a8023
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(s) (((s) & 0xff00) >> 8)
+#define WTERMSIG(s) ((s) & 0x7f)
+#define WSTOPSIG(s) WEXITSTATUS(s)
+#define WCOREDUMP(s) ((s) & 0x80)
+#define WIFEXITED(s) (!WTERMSIG(s))
+#define WIFSTOPPED(s) (((s) & 0xff) == 0x7f)
+#define WIFSIGNALED(s) (!WIFSTOPPED(s) && !WIFEXITED(s))
+#endif
diff --git a/include/byteswap.h b/include/byteswap.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/cpio.h b/include/cpio.h
new file mode 100644 (file)
index 0000000..39a1f8b
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _CPIO_H
+#define _CPIO_H
+
+#define MAGIC "070707"
+
+#define C_IRUSR  000400
+#define C_IWUSR  000200
+#define C_IXUSR  000100
+#define C_IRGRP  000040
+#define C_IWGRP  000020
+#define C_IXGRP  000010
+#define C_IROTH  000004
+#define C_IWOTH  000002
+#define C_IXOTH  000001
+
+#define C_ISUID  004000
+#define C_ISGID  002000
+#define C_ISVTX  001000
+
+#define C_ISBLK  060000
+#define C_ISCHR  020000
+#define C_ISDIR  040000
+#define C_ISFIFO 010000
+#define C_ISSOCK 0140000
+#define C_ISLNK  0120000
+#define C_ISCTG  0110000
+#define C_ISREG  0100000
+
+#endif
diff --git a/include/ctype.h b/include/ctype.h
new file mode 100644 (file)
index 0000000..02f81fa
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef        _CTYPE_H
+#define        _CTYPE_H
+
+int   isalnum(int);
+int   isalpha(int);
+int   isblank(int);
+int   iscntrl(int);
+int   isdigit(int);
+int   isgraph(int);
+int   islower(int);
+int   isprint(int);
+int   ispunct(int);
+int   isspace(int);
+int   isupper(int);
+int   isxdigit(int);
+int   tolower(int);
+int   toupper(int);
+
+int   isascii(int);
+int   toascii(int);
+
+#define _tolower(a) ((a)|0x20)
+#define _toupper(a) ((a)&0x5f)
+
+#define isalpha(a) ((unsigned)(((a)|32)-'a') < 26)
+#define isdigit(a) ((unsigned)((a)-'0') < 10)
+#define islower(a) ((unsigned)((a)-'a') < 26)
+#define isupper(a) ((unsigned)((a)-'A') < 26)
+#define isprint(a) ((unsigned)((a)-0x20) < 0x5f)
+#define isgraph(a) ((unsigned)((a)-0x21) < 0x5e)
+
+#if 1
+
+#define __NEED_locale_t
+#include <bits/alltypes.h>
+
+int   isalnum_l(int, locale_t);
+int   isalpha_l(int, locale_t);
+int   isblank_l(int, locale_t);
+int   iscntrl_l(int, locale_t);
+int   isdigit_l(int, locale_t);
+int   isgraph_l(int, locale_t);
+int   islower_l(int, locale_t);
+int   isprint_l(int, locale_t);
+int   ispunct_l(int, locale_t);
+int   isspace_l(int, locale_t);
+int   isupper_l(int, locale_t);
+int   isxdigit_l(int, locale_t);
+int   tolower_l(int, locale_t);
+int   toupper_l(int, locale_t);
+#endif
+
+#endif
diff --git a/include/dirent.h b/include/dirent.h
new file mode 100644 (file)
index 0000000..a917093
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef        _DIRENT_H
+#define        _DIRENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_ino_t
+#define __NEED_off_t
+
+#include <bits/alltypes.h>
+
+typedef struct __DIR_s DIR;
+
+struct dirent
+{
+       ino_t d_ino;
+       off_t d_off;
+       unsigned short d_reclen;
+       unsigned char d_type;
+       char d_name[1];
+};
+
+int            closedir(DIR *);
+DIR           *fdopendir(int);
+DIR           *opendir(const char *);
+struct dirent *readdir(DIR *);
+int            readdir_r(DIR *, struct dirent *, struct dirent **);
+void           rewinddir(DIR *);
+void           seekdir(DIR *, long);
+long           telldir(DIR *);
+int            dirfd(DIR *);
+
+int alphasort(const struct dirent **, const struct dirent **);
+int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **));
+
+#ifdef __cplusplus
+extern }
+#endif
+
+#endif
diff --git a/include/dlfcn.h b/include/dlfcn.h
new file mode 100644 (file)
index 0000000..81b829c
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef        _DLFCN_H
+#define        _DLFCN_H
+
+#define RTLD_LAZY   0x10000
+#define RTLD_NOW    0x20000
+#define RTLD_GLOBAL 0x40000
+#define RTLD_LOCAL  0x80000
+
+#if 1
+#define RTLD_NEXT    ((void *) -1l)
+#define RTLD_DEFAULT ((void *) 0)
+#endif
+
+int    dlclose(void *);
+char  *dlerror(void);
+void  *dlopen(const char *, int);
+void  *dlsym(void *, const char *);
+
+#endif
diff --git a/include/elf.h b/include/elf.h
new file mode 100644 (file)
index 0000000..b011e78
--- /dev/null
@@ -0,0 +1,2524 @@
+#ifndef _ELF_H
+#define        _ELF_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+typedef uint32_t Elf32_Word;
+typedef        int32_t  Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef        int32_t  Elf64_Sword;
+
+typedef uint64_t Elf32_Xword;
+typedef        int64_t  Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef        int64_t  Elf64_Sxword;
+
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+#define EI_NIDENT (16)
+
+typedef struct {
+  unsigned char        e_ident[EI_NIDENT];
+  Elf32_Half   e_type;
+  Elf32_Half   e_machine;
+  Elf32_Word   e_version;
+  Elf32_Addr   e_entry;
+  Elf32_Off    e_phoff;
+  Elf32_Off    e_shoff;
+  Elf32_Word   e_flags;
+  Elf32_Half   e_ehsize;
+  Elf32_Half   e_phentsize;
+  Elf32_Half   e_phnum;
+  Elf32_Half   e_shentsize;
+  Elf32_Half   e_shnum;
+  Elf32_Half   e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct {
+  unsigned char        e_ident[EI_NIDENT];
+  Elf64_Half   e_type;
+  Elf64_Half   e_machine;
+  Elf64_Word   e_version;
+  Elf64_Addr   e_entry;
+  Elf64_Off    e_phoff;
+  Elf64_Off    e_shoff;
+  Elf64_Word   e_flags;
+  Elf64_Half   e_ehsize;
+  Elf64_Half   e_phentsize;
+  Elf64_Half   e_phnum;
+  Elf64_Half   e_shentsize;
+  Elf64_Half   e_shnum;
+  Elf64_Half   e_shstrndx;
+} Elf64_Ehdr;
+
+#define EI_MAG0                0
+#define ELFMAG0                0x7f
+
+#define EI_MAG1                1
+#define ELFMAG1                'E'
+
+#define EI_MAG2                2
+#define ELFMAG2                'L'
+
+#define EI_MAG3                3
+#define ELFMAG3                'F'
+
+
+#define        ELFMAG          "\177ELF"
+#define        SELFMAG         4
+
+#define EI_CLASS       4
+#define ELFCLASSNONE   0
+#define ELFCLASS32     1
+#define ELFCLASS64     2
+#define ELFCLASSNUM    3
+
+#define EI_DATA                5
+#define ELFDATANONE    0
+#define ELFDATA2LSB    1
+#define ELFDATA2MSB    2
+#define ELFDATANUM     3
+
+#define EI_VERSION     6
+
+
+#define EI_OSABI       7
+#define ELFOSABI_NONE          0
+#define ELFOSABI_SYSV          0
+#define ELFOSABI_HPUX          1
+#define ELFOSABI_NETBSD                2
+#define ELFOSABI_LINUX         3
+#define ELFOSABI_SOLARIS       6
+#define ELFOSABI_AIX           7
+#define ELFOSABI_IRIX          8
+#define ELFOSABI_FREEBSD       9
+#define ELFOSABI_TRU64         10
+#define ELFOSABI_MODESTO       11
+#define ELFOSABI_OPENBSD       12
+#define ELFOSABI_ARM           97
+#define ELFOSABI_STANDALONE    255
+
+#define EI_ABIVERSION  8
+
+#define EI_PAD         9
+
+
+
+#define ET_NONE                0
+#define ET_REL         1
+#define ET_EXEC                2
+#define ET_DYN         3
+#define ET_CORE                4
+#define        ET_NUM          5
+#define ET_LOOS                0xfe00
+#define ET_HIOS                0xfeff
+#define ET_LOPROC      0xff00
+#define ET_HIPROC      0xffff
+
+
+
+#define EM_NONE                 0
+#define EM_M32          1
+#define EM_SPARC        2
+#define EM_386          3
+#define EM_68K          4
+#define EM_88K          5
+#define EM_860          7
+#define EM_MIPS                 8
+#define EM_S370                 9
+#define EM_MIPS_RS3_LE 10
+
+#define EM_PARISC      15
+#define EM_VPP500      17
+#define EM_SPARC32PLUS 18
+#define EM_960         19
+#define EM_PPC         20
+#define EM_PPC64       21
+#define EM_S390                22
+
+#define EM_V800                36
+#define EM_FR20                37
+#define EM_RH32                38
+#define EM_RCE         39
+#define EM_ARM         40
+#define EM_FAKE_ALPHA  41
+#define EM_SH          42
+#define EM_SPARCV9     43
+#define EM_TRICORE     44
+#define EM_ARC         45
+#define EM_H8_300      46
+#define EM_H8_300H     47
+#define EM_H8S         48
+#define EM_H8_500      49
+#define EM_IA_64       50
+#define EM_MIPS_X      51
+#define EM_COLDFIRE    52
+#define EM_68HC12      53
+#define EM_MMA         54
+#define EM_PCP         55
+#define EM_NCPU                56
+#define EM_NDR1                57
+#define EM_STARCORE    58
+#define EM_ME16                59
+#define EM_ST100       60
+#define EM_TINYJ       61
+#define EM_X86_64      62
+#define EM_PDSP                63
+
+#define EM_FX66                66
+#define EM_ST9PLUS     67
+#define EM_ST7         68
+#define EM_68HC16      69
+#define EM_68HC11      70
+#define EM_68HC08      71
+#define EM_68HC05      72
+#define EM_SVX         73
+#define EM_ST19                74
+#define EM_VAX         75
+#define EM_CRIS                76
+#define EM_JAVELIN     77
+#define EM_FIREPATH    78
+#define EM_ZSP         79
+#define EM_MMIX                80
+#define EM_HUANY       81
+#define EM_PRISM       82
+#define EM_AVR         83
+#define EM_FR30                84
+#define EM_D10V                85
+#define EM_D30V                86
+#define EM_V850                87
+#define EM_M32R                88
+#define EM_MN10300     89
+#define EM_MN10200     90
+#define EM_PJ          91
+#define EM_OPENRISC    92
+#define EM_ARC_A5      93
+#define EM_XTENSA      94
+#define EM_NUM         95
+#define EM_ALPHA       0x9026
+
+#define EV_NONE                0
+#define EV_CURRENT     1
+#define EV_NUM         2
+
+typedef struct {
+  Elf32_Word   sh_name;
+  Elf32_Word   sh_type;
+  Elf32_Word   sh_flags;
+  Elf32_Addr   sh_addr;
+  Elf32_Off    sh_offset;
+  Elf32_Word   sh_size;
+  Elf32_Word   sh_link;
+  Elf32_Word   sh_info;
+  Elf32_Word   sh_addralign;
+  Elf32_Word   sh_entsize;
+} Elf32_Shdr;
+
+typedef struct {
+  Elf64_Word   sh_name;
+  Elf64_Word   sh_type;
+  Elf64_Xword  sh_flags;
+  Elf64_Addr   sh_addr;
+  Elf64_Off    sh_offset;
+  Elf64_Xword  sh_size;
+  Elf64_Word   sh_link;
+  Elf64_Word   sh_info;
+  Elf64_Xword  sh_addralign;
+  Elf64_Xword  sh_entsize;
+} Elf64_Shdr;
+
+
+
+#define SHN_UNDEF      0
+#define SHN_LORESERVE  0xff00
+#define SHN_LOPROC     0xff00
+#define SHN_BEFORE     0xff00
+
+#define SHN_AFTER      0xff01
+
+#define SHN_HIPROC     0xff1f
+#define SHN_LOOS       0xff20
+#define SHN_HIOS       0xff3f
+#define SHN_ABS                0xfff1
+#define SHN_COMMON     0xfff2
+#define SHN_XINDEX     0xffff
+#define SHN_HIRESERVE  0xffff
+
+
+
+#define SHT_NULL         0
+#define SHT_PROGBITS     1
+#define SHT_SYMTAB       2
+#define SHT_STRTAB       3
+#define SHT_RELA         4
+#define SHT_HASH         5
+#define SHT_DYNAMIC      6
+#define SHT_NOTE         7
+#define SHT_NOBITS       8
+#define SHT_REL                  9
+#define SHT_SHLIB        10
+#define SHT_DYNSYM       11
+#define SHT_INIT_ARRAY   14
+#define SHT_FINI_ARRAY   15
+#define SHT_PREINIT_ARRAY 16
+#define SHT_GROUP        17
+#define SHT_SYMTAB_SHNDX  18
+#define        SHT_NUM           19
+#define SHT_LOOS         0x60000000
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5
+#define SHT_GNU_HASH     0x6ffffff6
+#define SHT_GNU_LIBLIST          0x6ffffff7
+#define SHT_CHECKSUM     0x6ffffff8
+#define SHT_LOSUNW       0x6ffffffa
+#define SHT_SUNW_move    0x6ffffffa
+#define SHT_SUNW_COMDAT   0x6ffffffb
+#define SHT_SUNW_syminfo  0x6ffffffc
+#define SHT_GNU_verdef   0x6ffffffd
+#define SHT_GNU_verneed          0x6ffffffe
+#define SHT_GNU_versym   0x6fffffff
+#define SHT_HISUNW       0x6fffffff
+#define SHT_HIOS         0x6fffffff
+#define SHT_LOPROC       0x70000000
+#define SHT_HIPROC       0x7fffffff
+#define SHT_LOUSER       0x80000000
+#define SHT_HIUSER       0x8fffffff
+
+#define SHF_WRITE           (1 << 0)
+#define SHF_ALLOC           (1 << 1)
+#define SHF_EXECINSTR       (1 << 2)
+#define SHF_MERGE           (1 << 4)
+#define SHF_STRINGS         (1 << 5)
+#define SHF_INFO_LINK       (1 << 6)
+#define SHF_LINK_ORDER      (1 << 7)
+#define SHF_OS_NONCONFORMING (1 << 8)
+
+#define SHF_GROUP           (1 << 9)
+#define SHF_TLS                     (1 << 10)
+#define SHF_MASKOS          0x0ff00000
+#define SHF_MASKPROC        0xf0000000
+#define SHF_ORDERED         (1 << 30)
+#define SHF_EXCLUDE         (1 << 31)
+
+#define GRP_COMDAT     0x1
+
+typedef struct {
+  Elf32_Word   st_name;
+  Elf32_Addr   st_value;
+  Elf32_Word   st_size;
+  unsigned char        st_info;
+  unsigned char        st_other;
+  Elf32_Section        st_shndx;
+} Elf32_Sym;
+
+typedef struct {
+  Elf64_Word   st_name;
+  unsigned char        st_info;
+  unsigned char st_other;
+  Elf64_Section        st_shndx;
+  Elf64_Addr   st_value;
+  Elf64_Xword  st_size;
+} Elf64_Sym;
+
+typedef struct {
+  Elf32_Half si_boundto;
+  Elf32_Half si_flags;
+} Elf32_Syminfo;
+
+typedef struct {
+  Elf64_Half si_boundto;
+  Elf64_Half si_flags;
+} Elf64_Syminfo;
+
+#define SYMINFO_BT_SELF                0xffff
+#define SYMINFO_BT_PARENT      0xfffe
+#define SYMINFO_BT_LOWRESERVE  0xff00
+
+#define SYMINFO_FLG_DIRECT     0x0001
+#define SYMINFO_FLG_PASSTHRU   0x0002
+#define SYMINFO_FLG_COPY       0x0004
+#define SYMINFO_FLG_LAZYLOAD   0x0008
+
+#define SYMINFO_NONE           0
+#define SYMINFO_CURRENT                1
+#define SYMINFO_NUM            2
+
+#define ELF32_ST_BIND(val)             (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)             ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
+
+#define ELF64_ST_BIND(val)             ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val)             ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type)      ELF32_ST_INFO ((bind), (type))
+
+#define STB_LOCAL      0
+#define STB_GLOBAL     1
+#define STB_WEAK       2
+#define        STB_NUM         3
+#define STB_LOOS       10
+#define STB_GNU_UNIQUE 10
+#define STB_HIOS       12
+#define STB_LOPROC     13
+#define STB_HIPROC     15
+
+#define STT_NOTYPE     0
+#define STT_OBJECT     1
+#define STT_FUNC       2
+#define STT_SECTION    3
+#define STT_FILE       4
+#define STT_COMMON     5
+#define STT_TLS                6
+#define        STT_NUM         7
+#define STT_LOOS       10
+#define STT_GNU_IFUNC  10
+#define STT_HIOS       12
+#define STT_LOPROC     13
+#define STT_HIPROC     15
+
+#define STN_UNDEF      0
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+#define STV_DEFAULT    0
+#define STV_INTERNAL   1
+#define STV_HIDDEN     2
+#define STV_PROTECTED  3
+
+
+
+
+typedef struct
+{
+  Elf32_Addr   r_offset;
+  Elf32_Word   r_info;
+} Elf32_Rel;
+
+typedef struct {
+  Elf64_Addr   r_offset;
+  Elf64_Xword  r_info;
+} Elf64_Rel;
+
+
+
+typedef struct {
+  Elf32_Addr   r_offset;
+  Elf32_Word   r_info;
+  Elf32_Sword  r_addend;
+} Elf32_Rela;
+
+typedef struct {
+  Elf64_Addr   r_offset;
+  Elf64_Xword  r_info;
+  Elf64_Sxword r_addend;
+} Elf64_Rela;
+
+
+
+#define ELF32_R_SYM(val)               ((val) >> 8)
+#define ELF32_R_TYPE(val)              ((val) & 0xff)
+#define ELF32_R_INFO(sym, type)                (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i)                 ((i) >> 32)
+#define ELF64_R_TYPE(i)                        ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)         ((((Elf64_Xword) (sym)) << 32) + (type))
+
+
+
+typedef struct {
+  Elf32_Word   p_type;
+  Elf32_Off    p_offset;
+  Elf32_Addr   p_vaddr;
+  Elf32_Addr   p_paddr;
+  Elf32_Word   p_filesz;
+  Elf32_Word   p_memsz;
+  Elf32_Word   p_flags;
+  Elf32_Word   p_align;
+} Elf32_Phdr;
+
+typedef struct {
+  Elf64_Word   p_type;
+  Elf64_Word   p_flags;
+  Elf64_Off    p_offset;
+  Elf64_Addr   p_vaddr;
+  Elf64_Addr   p_paddr;
+  Elf64_Xword  p_filesz;
+  Elf64_Xword  p_memsz;
+  Elf64_Xword  p_align;
+} Elf64_Phdr;
+
+
+
+#define        PT_NULL         0
+#define PT_LOAD                1
+#define PT_DYNAMIC     2
+#define PT_INTERP      3
+#define PT_NOTE                4
+#define PT_SHLIB       5
+#define PT_PHDR                6
+#define PT_TLS         7
+#define        PT_NUM          8
+#define PT_LOOS                0x60000000
+#define PT_GNU_EH_FRAME        0x6474e550
+#define PT_GNU_STACK   0x6474e551
+#define PT_GNU_RELRO   0x6474e552
+#define PT_LOSUNW      0x6ffffffa
+#define PT_SUNWBSS     0x6ffffffa
+#define PT_SUNWSTACK   0x6ffffffb
+#define PT_HISUNW      0x6fffffff
+#define PT_HIOS                0x6fffffff
+#define PT_LOPROC      0x70000000
+#define PT_HIPROC      0x7fffffff
+
+
+
+#define PF_X           (1 << 0)
+#define PF_W           (1 << 1)
+#define PF_R           (1 << 2)
+#define PF_MASKOS      0x0ff00000
+#define PF_MASKPROC    0xf0000000
+
+
+
+#define NT_PRSTATUS    1
+#define NT_FPREGSET    2
+#define NT_PRPSINFO    3
+#define NT_PRXREG      4
+#define NT_TASKSTRUCT  4
+#define NT_PLATFORM    5
+#define NT_AUXV                6
+#define NT_GWINDOWS    7
+#define NT_ASRS                8
+#define NT_PSTATUS     10
+#define NT_PSINFO      13
+#define NT_PRCRED      14
+#define NT_UTSNAME     15
+#define NT_LWPSTATUS   16
+#define NT_LWPSINFO    17
+#define NT_PRFPXREG    20
+#define NT_PRXFPREG    0x46e62b7f
+#define NT_PPC_VMX     0x100
+#define NT_PPC_SPE     0x101
+#define NT_PPC_VSX     0x102
+#define NT_386_TLS     0x200
+#define NT_386_IOPERM  0x201
+#define NT_VERSION     1
+
+
+
+
+typedef struct {
+  Elf32_Sword d_tag;
+  union {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+  } d_un;
+} Elf32_Dyn;
+
+typedef struct {
+  Elf64_Sxword d_tag;
+  union {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+  } d_un;
+} Elf64_Dyn;
+
+
+
+#define DT_NULL                0
+#define DT_NEEDED      1
+#define DT_PLTRELSZ    2
+#define DT_PLTGOT      3
+#define DT_HASH                4
+#define DT_STRTAB      5
+#define DT_SYMTAB      6
+#define DT_RELA                7
+#define DT_RELASZ      8
+#define DT_RELAENT     9
+#define DT_STRSZ       10
+#define DT_SYMENT      11
+#define DT_INIT                12
+#define DT_FINI                13
+#define DT_SONAME      14
+#define DT_RPATH       15
+#define DT_SYMBOLIC    16
+#define DT_REL         17
+#define DT_RELSZ       18
+#define DT_RELENT      19
+#define DT_PLTREL      20
+#define DT_DEBUG       21
+#define DT_TEXTREL     22
+#define DT_JMPREL      23
+#define        DT_BIND_NOW     24
+#define        DT_INIT_ARRAY   25
+#define        DT_FINI_ARRAY   26
+#define        DT_INIT_ARRAYSZ 27
+#define        DT_FINI_ARRAYSZ 28
+#define DT_RUNPATH     29
+#define DT_FLAGS       30
+#define DT_ENCODING    32
+#define DT_PREINIT_ARRAY 32
+#define DT_PREINIT_ARRAYSZ 33
+#define        DT_NUM          34
+#define DT_LOOS                0x6000000d
+#define DT_HIOS                0x6ffff000
+#define DT_LOPROC      0x70000000
+#define DT_HIPROC      0x7fffffff
+#define        DT_PROCNUM      DT_MIPS_NUM
+
+#define DT_VALRNGLO    0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7
+#define DT_CHECKSUM    0x6ffffdf8
+#define DT_PLTPADSZ    0x6ffffdf9
+#define DT_MOVEENT     0x6ffffdfa
+#define DT_MOVESZ      0x6ffffdfb
+#define DT_FEATURE_1   0x6ffffdfc
+#define DT_POSFLAG_1   0x6ffffdfd
+
+#define DT_SYMINSZ     0x6ffffdfe
+#define DT_SYMINENT    0x6ffffdff
+#define DT_VALRNGHI    0x6ffffdff
+#define DT_VALTAGIDX(tag)      (DT_VALRNGHI - (tag))
+#define DT_VALNUM 12
+
+#define DT_ADDRRNGLO   0x6ffffe00
+#define DT_GNU_HASH    0x6ffffef5
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
+#define DT_GNU_CONFLICT        0x6ffffef8
+#define DT_GNU_LIBLIST 0x6ffffef9
+#define DT_CONFIG      0x6ffffefa
+#define DT_DEPAUDIT    0x6ffffefb
+#define DT_AUDIT       0x6ffffefc
+#define        DT_PLTPAD       0x6ffffefd
+#define        DT_MOVETAB      0x6ffffefe
+#define DT_SYMINFO     0x6ffffeff
+#define DT_ADDRRNGHI   0x6ffffeff
+#define DT_ADDRTAGIDX(tag)     (DT_ADDRRNGHI - (tag))
+#define DT_ADDRNUM 11
+
+
+
+#define DT_VERSYM      0x6ffffff0
+
+#define DT_RELACOUNT   0x6ffffff9
+#define DT_RELCOUNT    0x6ffffffa
+
+
+#define DT_FLAGS_1     0x6ffffffb
+#define        DT_VERDEF       0x6ffffffc
+
+#define        DT_VERDEFNUM    0x6ffffffd
+#define        DT_VERNEED      0x6ffffffe
+
+#define        DT_VERNEEDNUM   0x6fffffff
+#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag))
+#define DT_VERSIONTAGNUM 16
+
+
+
+#define DT_AUXILIARY    0x7ffffffd
+#define DT_FILTER       0x7fffffff
+#define DT_EXTRATAGIDX(tag)    ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM    3
+
+
+#define DF_ORIGIN      0x00000001
+#define DF_SYMBOLIC    0x00000002
+#define DF_TEXTREL     0x00000004
+#define DF_BIND_NOW    0x00000008
+#define DF_STATIC_TLS  0x00000010
+
+
+
+#define DF_1_NOW       0x00000001
+#define DF_1_GLOBAL    0x00000002
+#define DF_1_GROUP     0x00000004
+#define DF_1_NODELETE  0x00000008
+#define DF_1_LOADFLTR  0x00000010
+#define DF_1_INITFIRST 0x00000020
+#define DF_1_NOOPEN    0x00000040
+#define DF_1_ORIGIN    0x00000080
+#define DF_1_DIRECT    0x00000100
+#define DF_1_TRANS     0x00000200
+#define DF_1_INTERPOSE 0x00000400
+#define DF_1_NODEFLIB  0x00000800
+#define DF_1_NODUMP    0x00001000
+#define DF_1_CONFALT   0x00002000
+#define DF_1_ENDFILTEE 0x00004000
+#define        DF_1_DISPRELDNE 0x00008000
+#define        DF_1_DISPRELPND 0x00010000
+
+
+#define DTF_1_PARINIT  0x00000001
+#define DTF_1_CONFEXP  0x00000002
+
+
+#define DF_P1_LAZYLOAD 0x00000001
+#define DF_P1_GROUPPERM        0x00000002
+
+
+
+
+typedef struct {
+  Elf32_Half   vd_version;
+  Elf32_Half   vd_flags;
+  Elf32_Half   vd_ndx;
+  Elf32_Half   vd_cnt;
+  Elf32_Word   vd_hash;
+  Elf32_Word   vd_aux;
+  Elf32_Word   vd_next;
+} Elf32_Verdef;
+
+typedef struct {
+  Elf64_Half   vd_version;
+  Elf64_Half   vd_flags;
+  Elf64_Half   vd_ndx;
+  Elf64_Half   vd_cnt;
+  Elf64_Word   vd_hash;
+  Elf64_Word   vd_aux;
+  Elf64_Word   vd_next;
+} Elf64_Verdef;
+
+
+
+#define VER_DEF_NONE   0
+#define VER_DEF_CURRENT        1
+#define VER_DEF_NUM    2
+
+
+#define VER_FLG_BASE   0x1
+#define VER_FLG_WEAK   0x2
+
+
+#define        VER_NDX_LOCAL           0
+#define        VER_NDX_GLOBAL          1
+#define        VER_NDX_LORESERVE       0xff00
+#define        VER_NDX_ELIMINATE       0xff01
+
+
+
+typedef struct {
+  Elf32_Word   vda_name;
+  Elf32_Word   vda_next;
+} Elf32_Verdaux;
+
+typedef struct {
+  Elf64_Word   vda_name;
+  Elf64_Word   vda_next;
+} Elf64_Verdaux;
+
+
+
+
+typedef struct {
+  Elf32_Half   vn_version;
+  Elf32_Half   vn_cnt;
+  Elf32_Word   vn_file;
+  Elf32_Word   vn_aux;
+  Elf32_Word   vn_next;
+} Elf32_Verneed;
+
+typedef struct {
+  Elf64_Half   vn_version;
+  Elf64_Half   vn_cnt;
+  Elf64_Word   vn_file;
+  Elf64_Word   vn_aux;
+  Elf64_Word   vn_next;
+} Elf64_Verneed;
+
+
+
+#define VER_NEED_NONE   0
+#define VER_NEED_CURRENT 1
+#define VER_NEED_NUM    2
+
+
+
+typedef struct {
+  Elf32_Word   vna_hash;
+  Elf32_Half   vna_flags;
+  Elf32_Half   vna_other;
+  Elf32_Word   vna_name;
+  Elf32_Word   vna_next;
+} Elf32_Vernaux;
+
+typedef struct {
+  Elf64_Word   vna_hash;
+  Elf64_Half   vna_flags;
+  Elf64_Half   vna_other;
+  Elf64_Word   vna_name;
+  Elf64_Word   vna_next;
+} Elf64_Vernaux;
+
+
+
+#define VER_FLG_WEAK   0x2
+
+
+
+typedef struct {
+  uint32_t a_type;
+  union {
+      uint32_t a_val;
+  } a_un;
+} Elf32_auxv_t;
+
+typedef struct {
+  uint64_t a_type;
+  union {
+      uint64_t a_val;
+  } a_un;
+} Elf64_auxv_t;
+
+
+
+#define AT_NULL                0
+#define AT_IGNORE      1
+#define AT_EXECFD      2
+#define AT_PHDR                3
+#define AT_PHENT       4
+#define AT_PHNUM       5
+#define AT_PAGESZ      6
+#define AT_BASE                7
+#define AT_FLAGS       8
+#define AT_ENTRY       9
+#define AT_NOTELF      10
+#define AT_UID         11
+#define AT_EUID                12
+#define AT_GID         13
+#define AT_EGID                14
+#define AT_CLKTCK      17
+
+
+#define AT_PLATFORM    15
+#define AT_HWCAP       16
+
+
+
+
+#define AT_FPUCW       18
+
+
+#define AT_DCACHEBSIZE 19
+#define AT_ICACHEBSIZE 20
+#define AT_UCACHEBSIZE 21
+
+
+
+#define AT_IGNOREPPC   22
+
+#define        AT_SECURE       23
+
+#define AT_BASE_PLATFORM 24
+
+#define AT_RANDOM      25
+
+#define AT_EXECFN      31
+
+
+
+#define AT_SYSINFO     32
+#define AT_SYSINFO_EHDR        33
+
+
+
+#define AT_L1I_CACHESHAPE      34
+#define AT_L1D_CACHESHAPE      35
+#define AT_L2_CACHESHAPE       36
+#define AT_L3_CACHESHAPE       37
+
+
+
+
+typedef struct {
+  Elf32_Word n_namesz;
+  Elf32_Word n_descsz;
+  Elf32_Word n_type;
+} Elf32_Nhdr;
+
+typedef struct {
+  Elf64_Word n_namesz;
+  Elf64_Word n_descsz;
+  Elf64_Word n_type;
+} Elf64_Nhdr;
+
+
+
+
+#define ELF_NOTE_SOLARIS       "SUNW Solaris"
+
+
+#define ELF_NOTE_GNU           "GNU"
+
+
+
+
+
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+#define NT_GNU_ABI_TAG 1
+#define ELF_NOTE_ABI   NT_GNU_ABI_TAG
+
+
+
+#define ELF_NOTE_OS_LINUX      0
+#define ELF_NOTE_OS_GNU                1
+#define ELF_NOTE_OS_SOLARIS2   2
+#define ELF_NOTE_OS_FREEBSD    3
+
+#define NT_GNU_BUILD_ID        3
+#define NT_GNU_GOLD_VERSION    4
+
+
+
+typedef struct {
+  Elf32_Xword m_value;
+  Elf32_Word m_info;
+  Elf32_Word m_poffset;
+  Elf32_Half m_repeat;
+  Elf32_Half m_stride;
+} Elf32_Move;
+
+typedef struct {
+  Elf64_Xword m_value;
+  Elf64_Xword m_info;
+  Elf64_Xword m_poffset;
+  Elf64_Half m_repeat;
+  Elf64_Half m_stride;
+} Elf64_Move;
+
+
+#define ELF32_M_SYM(info)      ((info) >> 8)
+#define ELF32_M_SIZE(info)     ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size)        (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info)      ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info)     ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size)        ELF32_M_INFO (sym, size)
+
+#define EF_CPU32       0x00810000
+
+#define R_68K_NONE     0
+#define R_68K_32       1
+#define R_68K_16       2
+#define R_68K_8                3
+#define R_68K_PC32     4
+#define R_68K_PC16     5
+#define R_68K_PC8      6
+#define R_68K_GOT32    7
+#define R_68K_GOT16    8
+#define R_68K_GOT8     9
+#define R_68K_GOT32O   10
+#define R_68K_GOT16O   11
+#define R_68K_GOT8O    12
+#define R_68K_PLT32    13
+#define R_68K_PLT16    14
+#define R_68K_PLT8     15
+#define R_68K_PLT32O   16
+#define R_68K_PLT16O   17
+#define R_68K_PLT8O    18
+#define R_68K_COPY     19
+#define R_68K_GLOB_DAT 20
+#define R_68K_JMP_SLOT 21
+#define R_68K_RELATIVE 22
+#define R_68K_NUM      23
+
+#define R_386_NONE        0
+#define R_386_32          1
+#define R_386_PC32        2
+#define R_386_GOT32       3
+#define R_386_PLT32       4
+#define R_386_COPY        5
+#define R_386_GLOB_DAT    6
+#define R_386_JMP_SLOT    7
+#define R_386_RELATIVE    8
+#define R_386_GOTOFF      9
+#define R_386_GOTPC       10
+#define R_386_32PLT       11
+#define R_386_TLS_TPOFF           14
+#define R_386_TLS_IE      15
+#define R_386_TLS_GOTIE           16
+#define R_386_TLS_LE      17
+#define R_386_TLS_GD      18
+#define R_386_TLS_LDM     19
+#define R_386_16          20
+#define R_386_PC16        21
+#define R_386_8                   22
+#define R_386_PC8         23
+#define R_386_TLS_GD_32           24
+#define R_386_TLS_GD_PUSH  25
+#define R_386_TLS_GD_CALL  26
+#define R_386_TLS_GD_POP   27
+#define R_386_TLS_LDM_32   28
+#define R_386_TLS_LDM_PUSH 29
+#define R_386_TLS_LDM_CALL 30
+#define R_386_TLS_LDM_POP  31
+#define R_386_TLS_LDO_32   32
+#define R_386_TLS_IE_32           33
+#define R_386_TLS_LE_32           34
+#define R_386_TLS_DTPMOD32 35
+#define R_386_TLS_DTPOFF32 36
+#define R_386_TLS_TPOFF32  37
+#define R_386_TLS_GOTDESC  39
+#define R_386_TLS_DESC_CALL 40
+#define R_386_TLS_DESC     41
+#define R_386_IRELATIVE           42
+#define R_386_NUM         43
+
+
+
+
+
+#define STT_SPARC_REGISTER     13
+
+
+
+#define EF_SPARCV9_MM          3
+#define EF_SPARCV9_TSO         0
+#define EF_SPARCV9_PSO         1
+#define EF_SPARCV9_RMO         2
+#define EF_SPARC_LEDATA                0x800000
+#define EF_SPARC_EXT_MASK      0xFFFF00
+#define EF_SPARC_32PLUS                0x000100
+#define EF_SPARC_SUN_US1       0x000200
+#define EF_SPARC_HAL_R1                0x000400
+#define EF_SPARC_SUN_US3       0x000800
+
+
+
+#define R_SPARC_NONE           0
+#define R_SPARC_8              1
+#define R_SPARC_16             2
+#define R_SPARC_32             3
+#define R_SPARC_DISP8          4
+#define R_SPARC_DISP16         5
+#define R_SPARC_DISP32         6
+#define R_SPARC_WDISP30                7
+#define R_SPARC_WDISP22                8
+#define R_SPARC_HI22           9
+#define R_SPARC_22             10
+#define R_SPARC_13             11
+#define R_SPARC_LO10           12
+#define R_SPARC_GOT10          13
+#define R_SPARC_GOT13          14
+#define R_SPARC_GOT22          15
+#define R_SPARC_PC10           16
+#define R_SPARC_PC22           17
+#define R_SPARC_WPLT30         18
+#define R_SPARC_COPY           19
+#define R_SPARC_GLOB_DAT       20
+#define R_SPARC_JMP_SLOT       21
+#define R_SPARC_RELATIVE       22
+#define R_SPARC_UA32           23
+
+
+
+#define R_SPARC_PLT32          24
+#define R_SPARC_HIPLT22                25
+#define R_SPARC_LOPLT10                26
+#define R_SPARC_PCPLT32                27
+#define R_SPARC_PCPLT22                28
+#define R_SPARC_PCPLT10                29
+#define R_SPARC_10             30
+#define R_SPARC_11             31
+#define R_SPARC_64             32
+#define R_SPARC_OLO10          33
+#define R_SPARC_HH22           34
+#define R_SPARC_HM10           35
+#define R_SPARC_LM22           36
+#define R_SPARC_PC_HH22                37
+#define R_SPARC_PC_HM10                38
+#define R_SPARC_PC_LM22                39
+#define R_SPARC_WDISP16                40
+#define R_SPARC_WDISP19                41
+#define R_SPARC_GLOB_JMP       42
+#define R_SPARC_7              43
+#define R_SPARC_5              44
+#define R_SPARC_6              45
+#define R_SPARC_DISP64         46
+#define R_SPARC_PLT64          47
+#define R_SPARC_HIX22          48
+#define R_SPARC_LOX10          49
+#define R_SPARC_H44            50
+#define R_SPARC_M44            51
+#define R_SPARC_L44            52
+#define R_SPARC_REGISTER       53
+#define R_SPARC_UA64           54
+#define R_SPARC_UA16           55
+#define R_SPARC_TLS_GD_HI22    56
+#define R_SPARC_TLS_GD_LO10    57
+#define R_SPARC_TLS_GD_ADD     58
+#define R_SPARC_TLS_GD_CALL    59
+#define R_SPARC_TLS_LDM_HI22   60
+#define R_SPARC_TLS_LDM_LO10   61
+#define R_SPARC_TLS_LDM_ADD    62
+#define R_SPARC_TLS_LDM_CALL   63
+#define R_SPARC_TLS_LDO_HIX22  64
+#define R_SPARC_TLS_LDO_LOX10  65
+#define R_SPARC_TLS_LDO_ADD    66
+#define R_SPARC_TLS_IE_HI22    67
+#define R_SPARC_TLS_IE_LO10    68
+#define R_SPARC_TLS_IE_LD      69
+#define R_SPARC_TLS_IE_LDX     70
+#define R_SPARC_TLS_IE_ADD     71
+#define R_SPARC_TLS_LE_HIX22   72
+#define R_SPARC_TLS_LE_LOX10   73
+#define R_SPARC_TLS_DTPMOD32   74
+#define R_SPARC_TLS_DTPMOD64   75
+#define R_SPARC_TLS_DTPOFF32   76
+#define R_SPARC_TLS_DTPOFF64   77
+#define R_SPARC_TLS_TPOFF32    78
+#define R_SPARC_TLS_TPOFF64    79
+#define R_SPARC_GOTDATA_HIX22  80
+#define R_SPARC_GOTDATA_LOX10  81
+#define R_SPARC_GOTDATA_OP_HIX22       82
+#define R_SPARC_GOTDATA_OP_LOX10       83
+#define R_SPARC_GOTDATA_OP     84
+#define R_SPARC_H34            85
+#define R_SPARC_SIZE32         86
+#define R_SPARC_SIZE64         87
+#define R_SPARC_GNU_VTINHERIT  250
+#define R_SPARC_GNU_VTENTRY    251
+#define R_SPARC_REV32          252
+
+#define R_SPARC_NUM            253
+
+
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM   2
+
+
+
+#define HWCAP_SPARC_FLUSH      1
+#define HWCAP_SPARC_STBAR      2
+#define HWCAP_SPARC_SWAP       4
+#define HWCAP_SPARC_MULDIV     8
+#define HWCAP_SPARC_V9         16
+#define HWCAP_SPARC_ULTRA3     32
+#define HWCAP_SPARC_BLKINIT    64
+#define HWCAP_SPARC_N2         128
+
+
+
+
+
+#define EF_MIPS_NOREORDER   1
+#define EF_MIPS_PIC        2
+#define EF_MIPS_CPIC       4
+#define EF_MIPS_XGOT       8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2       32
+#define EF_MIPS_ABI_ON32    64
+#define EF_MIPS_ARCH       0xf0000000
+
+
+
+#define EF_MIPS_ARCH_1     0x00000000
+#define EF_MIPS_ARCH_2     0x10000000
+#define EF_MIPS_ARCH_3     0x20000000
+#define EF_MIPS_ARCH_4     0x30000000
+#define EF_MIPS_ARCH_5     0x40000000
+#define EF_MIPS_ARCH_32            0x60000000
+#define EF_MIPS_ARCH_64            0x70000000
+
+
+
+#define E_MIPS_ARCH_1    0x00000000
+#define E_MIPS_ARCH_2    0x10000000
+#define E_MIPS_ARCH_3    0x20000000
+#define E_MIPS_ARCH_4    0x30000000
+#define E_MIPS_ARCH_5    0x40000000
+#define E_MIPS_ARCH_32   0x60000000
+#define E_MIPS_ARCH_64   0x70000000
+
+
+
+#define SHN_MIPS_ACOMMON    0xff00
+#define SHN_MIPS_TEXT      0xff01
+#define SHN_MIPS_DATA      0xff02
+#define SHN_MIPS_SCOMMON    0xff03
+#define SHN_MIPS_SUNDEFINED 0xff04
+
+
+
+#define SHT_MIPS_LIBLIST       0x70000000
+#define SHT_MIPS_MSYM         0x70000001
+#define SHT_MIPS_CONFLICT      0x70000002
+#define SHT_MIPS_GPTAB        0x70000003
+#define SHT_MIPS_UCODE        0x70000004
+#define SHT_MIPS_DEBUG        0x70000005
+#define SHT_MIPS_REGINFO       0x70000006
+#define SHT_MIPS_PACKAGE       0x70000007
+#define SHT_MIPS_PACKSYM       0x70000008
+#define SHT_MIPS_RELD         0x70000009
+#define SHT_MIPS_IFACE         0x7000000b
+#define SHT_MIPS_CONTENT       0x7000000c
+#define SHT_MIPS_OPTIONS       0x7000000d
+#define SHT_MIPS_SHDR         0x70000010
+#define SHT_MIPS_FDESC        0x70000011
+#define SHT_MIPS_EXTSYM               0x70000012
+#define SHT_MIPS_DENSE        0x70000013
+#define SHT_MIPS_PDESC        0x70000014
+#define SHT_MIPS_LOCSYM               0x70000015
+#define SHT_MIPS_AUXSYM               0x70000016
+#define SHT_MIPS_OPTSYM               0x70000017
+#define SHT_MIPS_LOCSTR               0x70000018
+#define SHT_MIPS_LINE         0x70000019
+#define SHT_MIPS_RFDESC               0x7000001a
+#define SHT_MIPS_DELTASYM      0x7000001b
+#define SHT_MIPS_DELTAINST     0x7000001c
+#define SHT_MIPS_DELTACLASS    0x7000001d
+#define SHT_MIPS_DWARF         0x7000001e
+#define SHT_MIPS_DELTADECL     0x7000001f
+#define SHT_MIPS_SYMBOL_LIB    0x70000020
+#define SHT_MIPS_EVENTS               0x70000021
+#define SHT_MIPS_TRANSLATE     0x70000022
+#define SHT_MIPS_PIXIE        0x70000023
+#define SHT_MIPS_XLATE        0x70000024
+#define SHT_MIPS_XLATE_DEBUG   0x70000025
+#define SHT_MIPS_WHIRL        0x70000026
+#define SHT_MIPS_EH_REGION     0x70000027
+#define SHT_MIPS_XLATE_OLD     0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+
+
+#define SHF_MIPS_GPREL  0x10000000
+#define SHF_MIPS_MERGE  0x20000000
+#define SHF_MIPS_ADDR   0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL  0x04000000
+#define SHF_MIPS_NAMES  0x02000000
+#define SHF_MIPS_NODUPE         0x01000000
+
+
+
+
+
+#define STO_MIPS_DEFAULT               0x0
+#define STO_MIPS_INTERNAL              0x1
+#define STO_MIPS_HIDDEN                        0x2
+#define STO_MIPS_PROTECTED             0x3
+#define STO_MIPS_PLT                   0x8
+#define STO_MIPS_SC_ALIGN_UNUSED       0xff
+
+
+#define STB_MIPS_SPLIT_COMMON          13
+
+
+
+typedef union {
+  struct {
+      Elf32_Word gt_current_g_value;
+      Elf32_Word gt_unused;
+  } gt_header;
+  struct {
+      Elf32_Word gt_g_value;
+      Elf32_Word gt_bytes;
+  } gt_entry;
+} Elf32_gptab;
+
+
+
+typedef struct {
+  Elf32_Word   ri_gprmask;
+  Elf32_Word   ri_cprmask[4];
+  Elf32_Sword  ri_gp_value;
+} Elf32_RegInfo;
+
+
+
+typedef struct {
+  unsigned char kind;
+
+  unsigned char size;
+  Elf32_Section section;
+
+  Elf32_Word info;
+} Elf_Options;
+
+
+
+#define ODK_NULL       0
+#define ODK_REGINFO    1
+#define ODK_EXCEPTIONS 2
+#define ODK_PAD                3
+#define ODK_HWPATCH    4
+#define ODK_FILL       5
+#define ODK_TAGS       6
+#define ODK_HWAND      7
+#define ODK_HWOR       8
+
+
+
+#define OEX_FPU_MIN    0x1f
+#define OEX_FPU_MAX    0x1f00
+#define OEX_PAGE0      0x10000
+#define OEX_SMM                0x20000
+#define OEX_FPDBUG     0x40000
+#define OEX_PRECISEFP  OEX_FPDBUG
+#define OEX_DISMISS    0x80000
+
+#define OEX_FPU_INVAL  0x10
+#define OEX_FPU_DIV0   0x08
+#define OEX_FPU_OFLO   0x04
+#define OEX_FPU_UFLO   0x02
+#define OEX_FPU_INEX   0x01
+
+
+
+#define OHW_R4KEOP     0x1
+#define OHW_R8KPFETCH  0x2
+#define OHW_R5KEOP     0x4
+#define OHW_R5KCVTL    0x8
+
+#define OPAD_PREFIX    0x1
+#define OPAD_POSTFIX   0x2
+#define OPAD_SYMBOL    0x4
+
+
+
+typedef struct {
+  Elf32_Word hwp_flags1;
+  Elf32_Word hwp_flags2;
+} Elf_Options_Hw;
+
+
+
+#define OHWA0_R4KEOP_CHECKED   0x00000001
+#define OHWA1_R4KEOP_CLEAN     0x00000002
+
+
+
+#define R_MIPS_NONE            0
+#define R_MIPS_16              1
+#define R_MIPS_32              2
+#define R_MIPS_REL32           3
+#define R_MIPS_26              4
+#define R_MIPS_HI16            5
+#define R_MIPS_LO16            6
+#define R_MIPS_GPREL16         7
+#define R_MIPS_LITERAL         8
+#define R_MIPS_GOT16           9
+#define R_MIPS_PC16            10
+#define R_MIPS_CALL16          11
+#define R_MIPS_GPREL32         12
+
+#define R_MIPS_SHIFT5          16
+#define R_MIPS_SHIFT6          17
+#define R_MIPS_64              18
+#define R_MIPS_GOT_DISP                19
+#define R_MIPS_GOT_PAGE                20
+#define R_MIPS_GOT_OFST                21
+#define R_MIPS_GOT_HI16                22
+#define R_MIPS_GOT_LO16                23
+#define R_MIPS_SUB             24
+#define R_MIPS_INSERT_A                25
+#define R_MIPS_INSERT_B                26
+#define R_MIPS_DELETE          27
+#define R_MIPS_HIGHER          28
+#define R_MIPS_HIGHEST         29
+#define R_MIPS_CALL_HI16       30
+#define R_MIPS_CALL_LO16       31
+#define R_MIPS_SCN_DISP                32
+#define R_MIPS_REL16           33
+#define R_MIPS_ADD_IMMEDIATE   34
+#define R_MIPS_PJUMP           35
+#define R_MIPS_RELGOT          36
+#define R_MIPS_JALR            37
+#define R_MIPS_TLS_DTPMOD32    38
+#define R_MIPS_TLS_DTPREL32    39
+#define R_MIPS_TLS_DTPMOD64    40
+#define R_MIPS_TLS_DTPREL64    41
+#define R_MIPS_TLS_GD          42
+#define R_MIPS_TLS_LDM         43
+#define R_MIPS_TLS_DTPREL_HI16 44
+#define R_MIPS_TLS_DTPREL_LO16 45
+#define R_MIPS_TLS_GOTTPREL    46
+#define R_MIPS_TLS_TPREL32     47
+#define R_MIPS_TLS_TPREL64     48
+#define R_MIPS_TLS_TPREL_HI16  49
+#define R_MIPS_TLS_TPREL_LO16  50
+#define R_MIPS_GLOB_DAT                51
+#define R_MIPS_COPY            126
+#define R_MIPS_JUMP_SLOT        127
+
+#define R_MIPS_NUM             128
+
+
+
+#define PT_MIPS_REGINFO        0x70000000
+#define PT_MIPS_RTPROC  0x70000001
+#define PT_MIPS_OPTIONS 0x70000002
+
+
+
+#define PF_MIPS_LOCAL  0x10000000
+
+
+
+#define DT_MIPS_RLD_VERSION  0x70000001
+#define DT_MIPS_TIME_STAMP   0x70000002
+#define DT_MIPS_ICHECKSUM    0x70000003
+#define DT_MIPS_IVERSION     0x70000004
+#define DT_MIPS_FLAGS       0x70000005
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_MSYM        0x70000007
+#define DT_MIPS_CONFLICT     0x70000008
+#define DT_MIPS_LIBLIST             0x70000009
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a
+#define DT_MIPS_CONFLICTNO   0x7000000b
+#define DT_MIPS_LIBLISTNO    0x70000010
+#define DT_MIPS_SYMTABNO     0x70000011
+#define DT_MIPS_UNREFEXTNO   0x70000012
+#define DT_MIPS_GOTSYM      0x70000013
+#define DT_MIPS_HIPAGENO     0x70000014
+#define DT_MIPS_RLD_MAP             0x70000016
+#define DT_MIPS_DELTA_CLASS  0x70000017
+#define DT_MIPS_DELTA_CLASS_NO    0x70000018
+
+#define DT_MIPS_DELTA_INSTANCE    0x70000019
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a
+
+#define DT_MIPS_DELTA_RELOC  0x7000001b
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c
+
+#define DT_MIPS_DELTA_SYM    0x7000001d
+
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e
+
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020
+
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021
+
+#define DT_MIPS_CXX_FLAGS    0x70000022
+#define DT_MIPS_PIXIE_INIT   0x70000023
+#define DT_MIPS_SYMBOL_LIB   0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS             0x70000029
+#define DT_MIPS_INTERFACE    0x7000002a
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d
+
+#define DT_MIPS_PERF_SUFFIX  0x7000002e
+
+#define DT_MIPS_COMPACT_SIZE 0x7000002f
+#define DT_MIPS_GP_VALUE     0x70000030
+#define DT_MIPS_AUX_DYNAMIC  0x70000031
+
+#define DT_MIPS_PLTGOT      0x70000032
+
+#define DT_MIPS_RWPLT        0x70000034
+#define DT_MIPS_NUM         0x35
+
+
+
+#define RHF_NONE                  0
+#define RHF_QUICKSTART            (1 << 0)
+#define RHF_NOTPOT                (1 << 1)
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)
+#define RHF_NO_MOVE               (1 << 3)
+#define RHF_SGI_ONLY              (1 << 4)
+#define RHF_GUARANTEE_INIT        (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS     (1 << 6)
+#define RHF_GUARANTEE_START_INIT   (1 << 7)
+#define RHF_PIXIE                 (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD    (1 << 9)
+#define RHF_REQUICKSTART          (1 << 10)
+#define RHF_REQUICKSTARTED        (1 << 11)
+#define RHF_CORD                  (1 << 12)
+#define RHF_NO_UNRES_UNDEF        (1 << 13)
+#define RHF_RLD_ORDER_SAFE        (1 << 14)
+
+
+
+typedef struct
+{
+  Elf32_Word l_name;
+  Elf32_Word l_time_stamp;
+  Elf32_Word l_checksum;
+  Elf32_Word l_version;
+  Elf32_Word l_flags;
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;
+  Elf64_Word l_time_stamp;
+  Elf64_Word l_checksum;
+  Elf64_Word l_version;
+  Elf64_Word l_flags;
+} Elf64_Lib;
+
+
+
+
+#define LL_NONE                  0
+#define LL_EXACT_MATCH   (1 << 0)
+#define LL_IGNORE_INT_VER (1 << 1)
+#define LL_REQUIRE_MINOR  (1 << 2)
+#define LL_EXPORTS       (1 << 3)
+#define LL_DELAY_LOAD    (1 << 4)
+#define LL_DELTA         (1 << 5)
+
+
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+
+
+
+
+#define EF_PARISC_TRAPNIL      0x00010000
+#define EF_PARISC_EXT          0x00020000
+#define EF_PARISC_LSB          0x00040000
+#define EF_PARISC_WIDE         0x00080000
+#define EF_PARISC_NO_KABP      0x00100000
+
+#define EF_PARISC_LAZYSWAP     0x00400000
+#define EF_PARISC_ARCH         0x0000ffff
+
+
+
+#define EFA_PARISC_1_0             0x020b
+#define EFA_PARISC_1_1             0x0210
+#define EFA_PARISC_2_0             0x0214
+
+
+
+#define SHN_PARISC_ANSI_COMMON 0xff00
+
+#define SHN_PARISC_HUGE_COMMON 0xff01
+
+
+
+#define SHT_PARISC_EXT         0x70000000
+#define SHT_PARISC_UNWIND      0x70000001
+#define SHT_PARISC_DOC         0x70000002
+
+
+
+#define SHF_PARISC_SHORT       0x20000000
+#define SHF_PARISC_HUGE                0x40000000
+#define SHF_PARISC_SBP         0x80000000
+
+
+
+#define STT_PARISC_MILLICODE   13
+
+#define STT_HP_OPAQUE          (STT_LOOS + 0x1)
+#define STT_HP_STUB            (STT_LOOS + 0x2)
+
+
+
+#define R_PARISC_NONE          0
+#define R_PARISC_DIR32         1
+#define R_PARISC_DIR21L                2
+#define R_PARISC_DIR17R                3
+#define R_PARISC_DIR17F                4
+#define R_PARISC_DIR14R                6
+#define R_PARISC_PCREL32       9
+#define R_PARISC_PCREL21L      10
+#define R_PARISC_PCREL17R      11
+#define R_PARISC_PCREL17F      12
+#define R_PARISC_PCREL14R      14
+#define R_PARISC_DPREL21L      18
+#define R_PARISC_DPREL14R      22
+#define R_PARISC_GPREL21L      26
+#define R_PARISC_GPREL14R      30
+#define R_PARISC_LTOFF21L      34
+#define R_PARISC_LTOFF14R      38
+#define R_PARISC_SECREL32      41
+#define R_PARISC_SEGBASE       48
+#define R_PARISC_SEGREL32      49
+#define R_PARISC_PLTOFF21L     50
+#define R_PARISC_PLTOFF14R     54
+#define R_PARISC_LTOFF_FPTR32  57
+#define R_PARISC_LTOFF_FPTR21L 58
+#define R_PARISC_LTOFF_FPTR14R 62
+#define R_PARISC_FPTR64                64
+#define R_PARISC_PLABEL32      65
+#define R_PARISC_PLABEL21L     66
+#define R_PARISC_PLABEL14R     70
+#define R_PARISC_PCREL64       72
+#define R_PARISC_PCREL22F      74
+#define R_PARISC_PCREL14WR     75
+#define R_PARISC_PCREL14DR     76
+#define R_PARISC_PCREL16F      77
+#define R_PARISC_PCREL16WF     78
+#define R_PARISC_PCREL16DF     79
+#define R_PARISC_DIR64         80
+#define R_PARISC_DIR14WR       83
+#define R_PARISC_DIR14DR       84
+#define R_PARISC_DIR16F                85
+#define R_PARISC_DIR16WF       86
+#define R_PARISC_DIR16DF       87
+#define R_PARISC_GPREL64       88
+#define R_PARISC_GPREL14WR     91
+#define R_PARISC_GPREL14DR     92
+#define R_PARISC_GPREL16F      93
+#define R_PARISC_GPREL16WF     94
+#define R_PARISC_GPREL16DF     95
+#define R_PARISC_LTOFF64       96
+#define R_PARISC_LTOFF14WR     99
+#define R_PARISC_LTOFF14DR     100
+#define R_PARISC_LTOFF16F      101
+#define R_PARISC_LTOFF16WF     102
+#define R_PARISC_LTOFF16DF     103
+#define R_PARISC_SECREL64      104
+#define R_PARISC_SEGREL64      112
+#define R_PARISC_PLTOFF14WR    115
+#define R_PARISC_PLTOFF14DR    116
+#define R_PARISC_PLTOFF16F     117
+#define R_PARISC_PLTOFF16WF    118
+#define R_PARISC_PLTOFF16DF    119
+#define R_PARISC_LTOFF_FPTR64  120
+#define R_PARISC_LTOFF_FPTR14WR        123
+#define R_PARISC_LTOFF_FPTR14DR        124
+#define R_PARISC_LTOFF_FPTR16F 125
+#define R_PARISC_LTOFF_FPTR16WF        126
+#define R_PARISC_LTOFF_FPTR16DF        127
+#define R_PARISC_LORESERVE     128
+#define R_PARISC_COPY          128
+#define R_PARISC_IPLT          129
+#define R_PARISC_EPLT          130
+#define R_PARISC_TPREL32       153
+#define R_PARISC_TPREL21L      154
+#define R_PARISC_TPREL14R      158
+#define R_PARISC_LTOFF_TP21L   162
+#define R_PARISC_LTOFF_TP14R   166
+#define R_PARISC_LTOFF_TP14F   167
+#define R_PARISC_TPREL64       216
+#define R_PARISC_TPREL14WR     219
+#define R_PARISC_TPREL14DR     220
+#define R_PARISC_TPREL16F      221
+#define R_PARISC_TPREL16WF     222
+#define R_PARISC_TPREL16DF     223
+#define R_PARISC_LTOFF_TP64    224
+#define R_PARISC_LTOFF_TP14WR  227
+#define R_PARISC_LTOFF_TP14DR  228
+#define R_PARISC_LTOFF_TP16F   229
+#define R_PARISC_LTOFF_TP16WF  230
+#define R_PARISC_LTOFF_TP16DF  231
+#define R_PARISC_GNU_VTENTRY   232
+#define R_PARISC_GNU_VTINHERIT 233
+#define R_PARISC_TLS_GD21L     234
+#define R_PARISC_TLS_GD14R     235
+#define R_PARISC_TLS_GDCALL    236
+#define R_PARISC_TLS_LDM21L    237
+#define R_PARISC_TLS_LDM14R    238
+#define R_PARISC_TLS_LDMCALL   239
+#define R_PARISC_TLS_LDO21L    240
+#define R_PARISC_TLS_LDO14R    241
+#define R_PARISC_TLS_DTPMOD32  242
+#define R_PARISC_TLS_DTPMOD64  243
+#define R_PARISC_TLS_DTPOFF32  244
+#define R_PARISC_TLS_DTPOFF64  245
+#define R_PARISC_TLS_LE21L     R_PARISC_TPREL21L
+#define R_PARISC_TLS_LE14R     R_PARISC_TPREL14R
+#define R_PARISC_TLS_IE21L     R_PARISC_LTOFF_TP21L
+#define R_PARISC_TLS_IE14R     R_PARISC_LTOFF_TP14R
+#define R_PARISC_TLS_TPREL32   R_PARISC_TPREL32
+#define R_PARISC_TLS_TPREL64   R_PARISC_TPREL64
+#define R_PARISC_HIRESERVE     255
+
+
+
+#define PT_HP_TLS              (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE                (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION     (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL      (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM                (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC                (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE    (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK       (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM         (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF         (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL         (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND         (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT                (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT                (PT_LOOS + 0x13)
+#define PT_HP_STACK            (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT      0x70000000
+#define PT_PARISC_UNWIND       0x70000001
+
+
+
+#define PF_PARISC_SBP          0x08000000
+
+#define PF_HP_PAGE_SIZE                0x00100000
+#define PF_HP_FAR_SHARED       0x00200000
+#define PF_HP_NEAR_SHARED      0x00400000
+#define PF_HP_CODE             0x01000000
+#define PF_HP_MODIFY           0x02000000
+#define PF_HP_LAZYSWAP         0x04000000
+#define PF_HP_SBP              0x08000000
+
+
+
+
+
+
+#define EF_ALPHA_32BIT         1
+#define EF_ALPHA_CANRELAX      2
+
+
+
+
+#define SHT_ALPHA_DEBUG                0x70000001
+#define SHT_ALPHA_REGINFO      0x70000002
+
+
+
+#define SHF_ALPHA_GPREL                0x10000000
+
+
+#define STO_ALPHA_NOPV         0x80
+#define STO_ALPHA_STD_GPLOAD   0x88
+
+
+
+#define R_ALPHA_NONE           0
+#define R_ALPHA_REFLONG                1
+#define R_ALPHA_REFQUAD                2
+#define R_ALPHA_GPREL32                3
+#define R_ALPHA_LITERAL                4
+#define R_ALPHA_LITUSE         5
+#define R_ALPHA_GPDISP         6
+#define R_ALPHA_BRADDR         7
+#define R_ALPHA_HINT           8
+#define R_ALPHA_SREL16         9
+#define R_ALPHA_SREL32         10
+#define R_ALPHA_SREL64         11
+#define R_ALPHA_GPRELHIGH      17
+#define R_ALPHA_GPRELLOW       18
+#define R_ALPHA_GPREL16                19
+#define R_ALPHA_COPY           24
+#define R_ALPHA_GLOB_DAT       25
+#define R_ALPHA_JMP_SLOT       26
+#define R_ALPHA_RELATIVE       27
+#define R_ALPHA_TLS_GD_HI      28
+#define R_ALPHA_TLSGD          29
+#define R_ALPHA_TLS_LDM                30
+#define R_ALPHA_DTPMOD64       31
+#define R_ALPHA_GOTDTPREL      32
+#define R_ALPHA_DTPREL64       33
+#define R_ALPHA_DTPRELHI       34
+#define R_ALPHA_DTPRELLO       35
+#define R_ALPHA_DTPREL16       36
+#define R_ALPHA_GOTTPREL       37
+#define R_ALPHA_TPREL64                38
+#define R_ALPHA_TPRELHI                39
+#define R_ALPHA_TPRELLO                40
+#define R_ALPHA_TPREL16                41
+
+#define R_ALPHA_NUM            46
+
+
+#define LITUSE_ALPHA_ADDR      0
+#define LITUSE_ALPHA_BASE      1
+#define LITUSE_ALPHA_BYTOFF    2
+#define LITUSE_ALPHA_JSR       3
+#define LITUSE_ALPHA_TLS_GD    4
+#define LITUSE_ALPHA_TLS_LDM   5
+
+
+#define DT_ALPHA_PLTRO         (DT_LOPROC + 0)
+#define DT_ALPHA_NUM           1
+
+
+
+
+#define EF_PPC_EMB             0x80000000
+
+
+#define EF_PPC_RELOCATABLE     0x00010000
+#define EF_PPC_RELOCATABLE_LIB 0x00008000
+
+
+
+#define R_PPC_NONE             0
+#define R_PPC_ADDR32           1
+#define R_PPC_ADDR24           2
+#define R_PPC_ADDR16           3
+#define R_PPC_ADDR16_LO                4
+#define R_PPC_ADDR16_HI                5
+#define R_PPC_ADDR16_HA                6
+#define R_PPC_ADDR14           7
+#define R_PPC_ADDR14_BRTAKEN   8
+#define R_PPC_ADDR14_BRNTAKEN  9
+#define R_PPC_REL24            10
+#define R_PPC_REL14            11
+#define R_PPC_REL14_BRTAKEN    12
+#define R_PPC_REL14_BRNTAKEN   13
+#define R_PPC_GOT16            14
+#define R_PPC_GOT16_LO         15
+#define R_PPC_GOT16_HI         16
+#define R_PPC_GOT16_HA         17
+#define R_PPC_PLTREL24         18
+#define R_PPC_COPY             19
+#define R_PPC_GLOB_DAT         20
+#define R_PPC_JMP_SLOT         21
+#define R_PPC_RELATIVE         22
+#define R_PPC_LOCAL24PC                23
+#define R_PPC_UADDR32          24
+#define R_PPC_UADDR16          25
+#define R_PPC_REL32            26
+#define R_PPC_PLT32            27
+#define R_PPC_PLTREL32         28
+#define R_PPC_PLT16_LO         29
+#define R_PPC_PLT16_HI         30
+#define R_PPC_PLT16_HA         31
+#define R_PPC_SDAREL16         32
+#define R_PPC_SECTOFF          33
+#define R_PPC_SECTOFF_LO       34
+#define R_PPC_SECTOFF_HI       35
+#define R_PPC_SECTOFF_HA       36
+
+
+#define R_PPC_TLS              67
+#define R_PPC_DTPMOD32         68
+#define R_PPC_TPREL16          69
+#define R_PPC_TPREL16_LO       70
+#define R_PPC_TPREL16_HI       71
+#define R_PPC_TPREL16_HA       72
+#define R_PPC_TPREL32          73
+#define R_PPC_DTPREL16         74
+#define R_PPC_DTPREL16_LO      75
+#define R_PPC_DTPREL16_HI      76
+#define R_PPC_DTPREL16_HA      77
+#define R_PPC_DTPREL32         78
+#define R_PPC_GOT_TLSGD16      79
+#define R_PPC_GOT_TLSGD16_LO   80
+#define R_PPC_GOT_TLSGD16_HI   81
+#define R_PPC_GOT_TLSGD16_HA   82
+#define R_PPC_GOT_TLSLD16      83
+#define R_PPC_GOT_TLSLD16_LO   84
+#define R_PPC_GOT_TLSLD16_HI   85
+#define R_PPC_GOT_TLSLD16_HA   86
+#define R_PPC_GOT_TPREL16      87
+#define R_PPC_GOT_TPREL16_LO   88
+#define R_PPC_GOT_TPREL16_HI   89
+#define R_PPC_GOT_TPREL16_HA   90
+#define R_PPC_GOT_DTPREL16     91
+#define R_PPC_GOT_DTPREL16_LO  92
+#define R_PPC_GOT_DTPREL16_HI  93
+#define R_PPC_GOT_DTPREL16_HA  94
+
+
+
+#define R_PPC_EMB_NADDR32      101
+#define R_PPC_EMB_NADDR16      102
+#define R_PPC_EMB_NADDR16_LO   103
+#define R_PPC_EMB_NADDR16_HI   104
+#define R_PPC_EMB_NADDR16_HA   105
+#define R_PPC_EMB_SDAI16       106
+#define R_PPC_EMB_SDA2I16      107
+#define R_PPC_EMB_SDA2REL      108
+#define R_PPC_EMB_SDA21                109
+#define R_PPC_EMB_MRKREF       110
+#define R_PPC_EMB_RELSEC16     111
+#define R_PPC_EMB_RELST_LO     112
+#define R_PPC_EMB_RELST_HI     113
+#define R_PPC_EMB_RELST_HA     114
+#define R_PPC_EMB_BIT_FLD      115
+#define R_PPC_EMB_RELSDA       116
+
+
+#define R_PPC_DIAB_SDA21_LO    180
+#define R_PPC_DIAB_SDA21_HI    181
+#define R_PPC_DIAB_SDA21_HA    182
+#define R_PPC_DIAB_RELSDA_LO   183
+#define R_PPC_DIAB_RELSDA_HI   184
+#define R_PPC_DIAB_RELSDA_HA   185
+
+
+#define R_PPC_IRELATIVE                248
+
+
+#define R_PPC_REL16            249
+#define R_PPC_REL16_LO         250
+#define R_PPC_REL16_HI         251
+#define R_PPC_REL16_HA         252
+
+
+
+#define R_PPC_TOC16            255
+
+
+#define DT_PPC_GOT             (DT_LOPROC + 0)
+#define DT_PPC_NUM             1
+
+
+#define R_PPC64_NONE           R_PPC_NONE
+#define R_PPC64_ADDR32         R_PPC_ADDR32
+#define R_PPC64_ADDR24         R_PPC_ADDR24
+#define R_PPC64_ADDR16         R_PPC_ADDR16
+#define R_PPC64_ADDR16_LO      R_PPC_ADDR16_LO
+#define R_PPC64_ADDR16_HI      R_PPC_ADDR16_HI
+#define R_PPC64_ADDR16_HA      R_PPC_ADDR16_HA
+#define R_PPC64_ADDR14         R_PPC_ADDR14
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN        R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24          R_PPC_REL24
+#define R_PPC64_REL14          R_PPC_REL14
+#define R_PPC64_REL14_BRTAKEN  R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16          R_PPC_GOT16
+#define R_PPC64_GOT16_LO       R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI       R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA       R_PPC_GOT16_HA
+
+#define R_PPC64_COPY           R_PPC_COPY
+#define R_PPC64_GLOB_DAT       R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT       R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE       R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32                R_PPC_UADDR32
+#define R_PPC64_UADDR16                R_PPC_UADDR16
+#define R_PPC64_REL32          R_PPC_REL32
+#define R_PPC64_PLT32          R_PPC_PLT32
+#define R_PPC64_PLTREL32       R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO       R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI       R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA       R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF                R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO     R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI     R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA     R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30         37
+#define R_PPC64_ADDR64         38
+#define R_PPC64_ADDR16_HIGHER  39
+#define R_PPC64_ADDR16_HIGHERA 40
+#define R_PPC64_ADDR16_HIGHEST 41
+#define R_PPC64_ADDR16_HIGHESTA        42
+#define R_PPC64_UADDR64                43
+#define R_PPC64_REL64          44
+#define R_PPC64_PLT64          45
+#define R_PPC64_PLTREL64       46
+#define R_PPC64_TOC16          47
+#define R_PPC64_TOC16_LO       48
+#define R_PPC64_TOC16_HI       49
+#define R_PPC64_TOC16_HA       50
+#define R_PPC64_TOC            51
+#define R_PPC64_PLTGOT16       52
+#define R_PPC64_PLTGOT16_LO    53
+#define R_PPC64_PLTGOT16_HI    54
+#define R_PPC64_PLTGOT16_HA    55
+
+#define R_PPC64_ADDR16_DS      56
+#define R_PPC64_ADDR16_LO_DS   57
+#define R_PPC64_GOT16_DS       58
+#define R_PPC64_GOT16_LO_DS    59
+#define R_PPC64_PLT16_LO_DS    60
+#define R_PPC64_SECTOFF_DS     61
+#define R_PPC64_SECTOFF_LO_DS  62
+#define R_PPC64_TOC16_DS       63
+#define R_PPC64_TOC16_LO_DS    64
+#define R_PPC64_PLTGOT16_DS    65
+#define R_PPC64_PLTGOT16_LO_DS 66
+
+
+#define R_PPC64_TLS            67
+#define R_PPC64_DTPMOD64       68
+#define R_PPC64_TPREL16                69
+#define R_PPC64_TPREL16_LO     70
+#define R_PPC64_TPREL16_HI     71
+#define R_PPC64_TPREL16_HA     72
+#define R_PPC64_TPREL64                73
+#define R_PPC64_DTPREL16       74
+#define R_PPC64_DTPREL16_LO    75
+#define R_PPC64_DTPREL16_HI    76
+#define R_PPC64_DTPREL16_HA    77
+#define R_PPC64_DTPREL64       78
+#define R_PPC64_GOT_TLSGD16    79
+#define R_PPC64_GOT_TLSGD16_LO 80
+#define R_PPC64_GOT_TLSGD16_HI 81
+#define R_PPC64_GOT_TLSGD16_HA 82
+#define R_PPC64_GOT_TLSLD16    83
+#define R_PPC64_GOT_TLSLD16_LO 84
+#define R_PPC64_GOT_TLSLD16_HI 85
+#define R_PPC64_GOT_TLSLD16_HA 86
+#define R_PPC64_GOT_TPREL16_DS 87
+#define R_PPC64_GOT_TPREL16_LO_DS 88
+#define R_PPC64_GOT_TPREL16_HI 89
+#define R_PPC64_GOT_TPREL16_HA 90
+#define R_PPC64_GOT_DTPREL16_DS        91
+#define R_PPC64_GOT_DTPREL16_LO_DS 92
+#define R_PPC64_GOT_DTPREL16_HI        93
+#define R_PPC64_GOT_DTPREL16_HA        94
+#define R_PPC64_TPREL16_DS     95
+#define R_PPC64_TPREL16_LO_DS  96
+#define R_PPC64_TPREL16_HIGHER 97
+#define R_PPC64_TPREL16_HIGHERA        98
+#define R_PPC64_TPREL16_HIGHEST        99
+#define R_PPC64_TPREL16_HIGHESTA 100
+#define R_PPC64_DTPREL16_DS    101
+#define R_PPC64_DTPREL16_LO_DS 102
+#define R_PPC64_DTPREL16_HIGHER        103
+#define R_PPC64_DTPREL16_HIGHERA 104
+#define R_PPC64_DTPREL16_HIGHEST 105
+#define R_PPC64_DTPREL16_HIGHESTA 106
+
+
+#define R_PPC64_JMP_IREL       247
+#define R_PPC64_IRELATIVE      248
+#define R_PPC64_REL16          249
+#define R_PPC64_REL16_LO       250
+#define R_PPC64_REL16_HI       251
+#define R_PPC64_REL16_HA       252
+
+
+#define DT_PPC64_GLINK  (DT_LOPROC + 0)
+#define DT_PPC64_OPD   (DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_NUM    3
+
+
+
+
+
+#define EF_ARM_RELEXEC         0x01
+#define EF_ARM_HASENTRY                0x02
+#define EF_ARM_INTERWORK       0x04
+#define EF_ARM_APCS_26         0x08
+#define EF_ARM_APCS_FLOAT      0x10
+#define EF_ARM_PIC             0x20
+#define EF_ARM_ALIGN8          0x40
+#define EF_ARM_NEW_ABI         0x80
+#define EF_ARM_OLD_ABI         0x100
+#define EF_ARM_SOFT_FLOAT      0x200
+#define EF_ARM_VFP_FLOAT       0x400
+#define EF_ARM_MAVERICK_FLOAT  0x800
+
+
+
+
+#define EF_ARM_SYMSARESORTED   0x04
+#define EF_ARM_DYNSYMSUSESEGIDX        0x08
+#define EF_ARM_MAPSYMSFIRST    0x10
+#define EF_ARM_EABIMASK                0XFF000000
+
+
+#define EF_ARM_BE8         0x00800000
+#define EF_ARM_LE8         0x00400000
+
+#define EF_ARM_EABI_VERSION(flags)     ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN    0x00000000
+#define EF_ARM_EABI_VER1       0x01000000
+#define EF_ARM_EABI_VER2       0x02000000
+#define EF_ARM_EABI_VER3       0x03000000
+#define EF_ARM_EABI_VER4       0x04000000
+#define EF_ARM_EABI_VER5       0x05000000
+
+
+#define STT_ARM_TFUNC          STT_LOPROC
+#define STT_ARM_16BIT          STT_HIPROC
+
+
+#define SHF_ARM_ENTRYSECT      0x10000000
+#define SHF_ARM_COMDEF         0x80000000
+
+
+
+#define PF_ARM_SB              0x10000000
+
+#define PF_ARM_PI              0x20000000
+#define PF_ARM_ABS             0x40000000
+
+
+#define PT_ARM_EXIDX           (PT_LOPROC + 1)
+
+
+#define SHT_ARM_EXIDX          (SHT_LOPROC + 1)
+#define SHT_ARM_PREEMPTMAP     (SHT_LOPROC + 2)
+#define SHT_ARM_ATTRIBUTES     (SHT_LOPROC + 3)
+
+
+
+
+#define R_ARM_NONE             0
+#define R_ARM_PC24             1
+#define R_ARM_ABS32            2
+#define R_ARM_REL32            3
+#define R_ARM_PC13             4
+#define R_ARM_ABS16            5
+#define R_ARM_ABS12            6
+#define R_ARM_THM_ABS5         7
+#define R_ARM_ABS8             8
+#define R_ARM_SBREL32          9
+#define R_ARM_THM_PC22         10
+#define R_ARM_THM_PC8          11
+#define R_ARM_AMP_VCALL9       12
+#define R_ARM_SWI24            13
+#define R_ARM_THM_SWI8         14
+#define R_ARM_XPC25            15
+#define R_ARM_THM_XPC22                16
+#define R_ARM_TLS_DTPMOD32     17
+#define R_ARM_TLS_DTPOFF32     18
+#define R_ARM_TLS_TPOFF32      19
+#define R_ARM_COPY             20
+#define R_ARM_GLOB_DAT         21
+#define R_ARM_JUMP_SLOT                22
+#define R_ARM_RELATIVE         23
+#define R_ARM_GOTOFF           24
+#define R_ARM_GOTPC            25
+#define R_ARM_GOT32            26
+#define R_ARM_PLT32            27
+#define R_ARM_ALU_PCREL_7_0    32
+#define R_ARM_ALU_PCREL_15_8   33
+#define R_ARM_ALU_PCREL_23_15  34
+#define R_ARM_LDR_SBREL_11_0   35
+#define R_ARM_ALU_SBREL_19_12  36
+#define R_ARM_ALU_SBREL_27_20  37
+#define R_ARM_GNU_VTENTRY      100
+#define R_ARM_GNU_VTINHERIT    101
+#define R_ARM_THM_PC11         102
+#define R_ARM_THM_PC9          103
+#define R_ARM_TLS_GD32         104
+
+#define R_ARM_TLS_LDM32                105
+
+#define R_ARM_TLS_LDO32                106
+
+#define R_ARM_TLS_IE32         107
+
+#define R_ARM_TLS_LE32         108
+
+#define R_ARM_RXPC25           249
+#define R_ARM_RSBREL32         250
+#define R_ARM_THM_RPC22                251
+#define R_ARM_RREL32           252
+#define R_ARM_RABS22           253
+#define R_ARM_RPC24            254
+#define R_ARM_RBASE            255
+
+#define R_ARM_NUM              256
+
+
+
+
+#define EF_IA_64_MASKOS                0x0000000f
+#define EF_IA_64_ABI64         0x00000010
+#define EF_IA_64_ARCH          0xff000000
+
+
+#define PT_IA_64_ARCHEXT       (PT_LOPROC + 0)
+#define PT_IA_64_UNWIND                (PT_LOPROC + 1)
+#define PT_IA_64_HP_OPT_ANOT   (PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT   (PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK      (PT_LOOS + 0x14)
+
+
+#define PF_IA_64_NORECOV       0x80000000
+
+
+#define SHT_IA_64_EXT          (SHT_LOPROC + 0)
+#define SHT_IA_64_UNWIND       (SHT_LOPROC + 1)
+
+
+#define SHF_IA_64_SHORT                0x10000000
+#define SHF_IA_64_NORECOV      0x20000000
+
+
+#define DT_IA_64_PLT_RESERVE   (DT_LOPROC + 0)
+#define DT_IA_64_NUM           1
+
+
+#define R_IA64_NONE            0x00
+#define R_IA64_IMM14           0x21
+#define R_IA64_IMM22           0x22
+#define R_IA64_IMM64           0x23
+#define R_IA64_DIR32MSB                0x24
+#define R_IA64_DIR32LSB                0x25
+#define R_IA64_DIR64MSB                0x26
+#define R_IA64_DIR64LSB                0x27
+#define R_IA64_GPREL22         0x2a
+#define R_IA64_GPREL64I                0x2b
+#define R_IA64_GPREL32MSB      0x2c
+#define R_IA64_GPREL32LSB      0x2d
+#define R_IA64_GPREL64MSB      0x2e
+#define R_IA64_GPREL64LSB      0x2f
+#define R_IA64_LTOFF22         0x32
+#define R_IA64_LTOFF64I                0x33
+#define R_IA64_PLTOFF22                0x3a
+#define R_IA64_PLTOFF64I       0x3b
+#define R_IA64_PLTOFF64MSB     0x3e
+#define R_IA64_PLTOFF64LSB     0x3f
+#define R_IA64_FPTR64I         0x43
+#define R_IA64_FPTR32MSB       0x44
+#define R_IA64_FPTR32LSB       0x45
+#define R_IA64_FPTR64MSB       0x46
+#define R_IA64_FPTR64LSB       0x47
+#define R_IA64_PCREL60B                0x48
+#define R_IA64_PCREL21B                0x49
+#define R_IA64_PCREL21M                0x4a
+#define R_IA64_PCREL21F                0x4b
+#define R_IA64_PCREL32MSB      0x4c
+#define R_IA64_PCREL32LSB      0x4d
+#define R_IA64_PCREL64MSB      0x4e
+#define R_IA64_PCREL64LSB      0x4f
+#define R_IA64_LTOFF_FPTR22    0x52
+#define R_IA64_LTOFF_FPTR64I   0x53
+#define R_IA64_LTOFF_FPTR32MSB 0x54
+#define R_IA64_LTOFF_FPTR32LSB 0x55
+#define R_IA64_LTOFF_FPTR64MSB 0x56
+#define R_IA64_LTOFF_FPTR64LSB 0x57
+#define R_IA64_SEGREL32MSB     0x5c
+#define R_IA64_SEGREL32LSB     0x5d
+#define R_IA64_SEGREL64MSB     0x5e
+#define R_IA64_SEGREL64LSB     0x5f
+#define R_IA64_SECREL32MSB     0x64
+#define R_IA64_SECREL32LSB     0x65
+#define R_IA64_SECREL64MSB     0x66
+#define R_IA64_SECREL64LSB     0x67
+#define R_IA64_REL32MSB                0x6c
+#define R_IA64_REL32LSB                0x6d
+#define R_IA64_REL64MSB                0x6e
+#define R_IA64_REL64LSB                0x6f
+#define R_IA64_LTV32MSB                0x74
+#define R_IA64_LTV32LSB                0x75
+#define R_IA64_LTV64MSB                0x76
+#define R_IA64_LTV64LSB                0x77
+#define R_IA64_PCREL21BI       0x79
+#define R_IA64_PCREL22         0x7a
+#define R_IA64_PCREL64I                0x7b
+#define R_IA64_IPLTMSB         0x80
+#define R_IA64_IPLTLSB         0x81
+#define R_IA64_COPY            0x84
+#define R_IA64_SUB             0x85
+#define R_IA64_LTOFF22X                0x86
+#define R_IA64_LDXMOV          0x87
+#define R_IA64_TPREL14         0x91
+#define R_IA64_TPREL22         0x92
+#define R_IA64_TPREL64I                0x93
+#define R_IA64_TPREL64MSB      0x96
+#define R_IA64_TPREL64LSB      0x97
+#define R_IA64_LTOFF_TPREL22   0x9a
+#define R_IA64_DTPMOD64MSB     0xa6
+#define R_IA64_DTPMOD64LSB     0xa7
+#define R_IA64_LTOFF_DTPMOD22  0xaa
+#define R_IA64_DTPREL14                0xb1
+#define R_IA64_DTPREL22                0xb2
+#define R_IA64_DTPREL64I       0xb3
+#define R_IA64_DTPREL32MSB     0xb4
+#define R_IA64_DTPREL32LSB     0xb5
+#define R_IA64_DTPREL64MSB     0xb6
+#define R_IA64_DTPREL64LSB     0xb7
+#define R_IA64_LTOFF_DTPREL22  0xba
+
+
+
+
+#define        R_SH_NONE               0
+#define        R_SH_DIR32              1
+#define        R_SH_REL32              2
+#define        R_SH_DIR8WPN            3
+#define        R_SH_IND12W             4
+#define        R_SH_DIR8WPL            5
+#define        R_SH_DIR8WPZ            6
+#define        R_SH_DIR8BP             7
+#define        R_SH_DIR8W              8
+#define        R_SH_DIR8L              9
+#define        R_SH_SWITCH16           25
+#define        R_SH_SWITCH32           26
+#define        R_SH_USES               27
+#define        R_SH_COUNT              28
+#define        R_SH_ALIGN              29
+#define        R_SH_CODE               30
+#define        R_SH_DATA               31
+#define        R_SH_LABEL              32
+#define        R_SH_SWITCH8            33
+#define        R_SH_GNU_VTINHERIT      34
+#define        R_SH_GNU_VTENTRY        35
+#define        R_SH_TLS_GD_32          144
+#define        R_SH_TLS_LD_32          145
+#define        R_SH_TLS_LDO_32         146
+#define        R_SH_TLS_IE_32          147
+#define        R_SH_TLS_LE_32          148
+#define        R_SH_TLS_DTPMOD32       149
+#define        R_SH_TLS_DTPOFF32       150
+#define        R_SH_TLS_TPOFF32        151
+#define        R_SH_GOT32              160
+#define        R_SH_PLT32              161
+#define        R_SH_COPY               162
+#define        R_SH_GLOB_DAT           163
+#define        R_SH_JMP_SLOT           164
+#define        R_SH_RELATIVE           165
+#define        R_SH_GOTOFF             166
+#define        R_SH_GOTPC              167
+
+#define        R_SH_NUM                256
+
+
+
+#define R_390_NONE             0
+#define R_390_8                        1
+#define R_390_12               2
+#define R_390_16               3
+#define R_390_32               4
+#define R_390_PC32             5
+#define R_390_GOT12            6
+#define R_390_GOT32            7
+#define R_390_PLT32            8
+#define R_390_COPY             9
+#define R_390_GLOB_DAT         10
+#define R_390_JMP_SLOT         11
+#define R_390_RELATIVE         12
+#define R_390_GOTOFF32         13
+#define R_390_GOTPC            14
+#define R_390_GOT16            15
+#define R_390_PC16             16
+#define R_390_PC16DBL          17
+#define R_390_PLT16DBL         18
+#define R_390_PC32DBL          19
+#define R_390_PLT32DBL         20
+#define R_390_GOTPCDBL         21
+#define R_390_64               22
+#define R_390_PC64             23
+#define R_390_GOT64            24
+#define R_390_PLT64            25
+#define R_390_GOTENT           26
+#define R_390_GOTOFF16         27
+#define R_390_GOTOFF64         28
+#define R_390_GOTPLT12         29
+#define R_390_GOTPLT16         30
+#define R_390_GOTPLT32         31
+#define R_390_GOTPLT64         32
+#define R_390_GOTPLTENT                33
+#define R_390_PLTOFF16         34
+#define R_390_PLTOFF32         35
+#define R_390_PLTOFF64         36
+#define R_390_TLS_LOAD         37
+#define R_390_TLS_GDCALL       38
+
+#define R_390_TLS_LDCALL       39
+
+#define R_390_TLS_GD32         40
+
+#define R_390_TLS_GD64         41
+
+#define R_390_TLS_GOTIE12      42
+
+#define R_390_TLS_GOTIE32      43
+
+#define R_390_TLS_GOTIE64      44
+
+#define R_390_TLS_LDM32                45
+
+#define R_390_TLS_LDM64                46
+
+#define R_390_TLS_IE32         47
+
+#define R_390_TLS_IE64         48
+
+#define R_390_TLS_IEENT                49
+
+#define R_390_TLS_LE32         50
+
+#define R_390_TLS_LE64         51
+
+#define R_390_TLS_LDO32                52
+
+#define R_390_TLS_LDO64                53
+
+#define R_390_TLS_DTPMOD       54
+#define R_390_TLS_DTPOFF       55
+#define R_390_TLS_TPOFF                56
+
+#define R_390_20               57
+#define R_390_GOT20            58
+#define R_390_GOTPLT20         59
+#define R_390_TLS_GOTIE20      60
+
+
+#define R_390_NUM              61
+
+
+
+#define R_CRIS_NONE            0
+#define R_CRIS_8               1
+#define R_CRIS_16              2
+#define R_CRIS_32              3
+#define R_CRIS_8_PCREL         4
+#define R_CRIS_16_PCREL                5
+#define R_CRIS_32_PCREL                6
+#define R_CRIS_GNU_VTINHERIT   7
+#define R_CRIS_GNU_VTENTRY     8
+#define R_CRIS_COPY            9
+#define R_CRIS_GLOB_DAT                10
+#define R_CRIS_JUMP_SLOT       11
+#define R_CRIS_RELATIVE                12
+#define R_CRIS_16_GOT          13
+#define R_CRIS_32_GOT          14
+#define R_CRIS_16_GOTPLT       15
+#define R_CRIS_32_GOTPLT       16
+#define R_CRIS_32_GOTREL       17
+#define R_CRIS_32_PLT_GOTREL   18
+#define R_CRIS_32_PLT_PCREL    19
+
+#define R_CRIS_NUM             20
+
+
+
+#define R_X86_64_NONE          0
+#define R_X86_64_64            1
+#define R_X86_64_PC32          2
+#define R_X86_64_GOT32         3
+#define R_X86_64_PLT32         4
+#define R_X86_64_COPY          5
+#define R_X86_64_GLOB_DAT      6
+#define R_X86_64_JUMP_SLOT     7
+#define R_X86_64_RELATIVE      8
+#define R_X86_64_GOTPCREL      9
+
+#define R_X86_64_32            10
+#define R_X86_64_32S           11
+#define R_X86_64_16            12
+#define R_X86_64_PC16          13
+#define R_X86_64_8             14
+#define R_X86_64_PC8           15
+#define R_X86_64_DTPMOD64      16
+#define R_X86_64_DTPOFF64      17
+#define R_X86_64_TPOFF64       18
+#define R_X86_64_TLSGD         19
+
+#define R_X86_64_TLSLD         20
+
+#define R_X86_64_DTPOFF32      21
+#define R_X86_64_GOTTPOFF      22
+
+#define R_X86_64_TPOFF32       23
+#define R_X86_64_PC64          24
+#define R_X86_64_GOTOFF64      25
+#define R_X86_64_GOTPC32       26
+
+
+#define R_X86_64_GOTPC32_TLSDESC 34
+#define R_X86_64_TLSDESC_CALL   35
+
+#define R_X86_64_TLSDESC        36
+#define R_X86_64_IRELATIVE     37
+
+#define R_X86_64_NUM           38
+
+
+
+#define R_MN10300_NONE         0
+#define R_MN10300_32           1
+#define R_MN10300_16           2
+#define R_MN10300_8            3
+#define R_MN10300_PCREL32      4
+#define R_MN10300_PCREL16      5
+#define R_MN10300_PCREL8       6
+#define R_MN10300_GNU_VTINHERIT        7
+#define R_MN10300_GNU_VTENTRY  8
+#define R_MN10300_24           9
+#define R_MN10300_GOTPC32      10
+#define R_MN10300_GOTPC16      11
+#define R_MN10300_GOTOFF32     12
+#define R_MN10300_GOTOFF24     13
+#define R_MN10300_GOTOFF16     14
+#define R_MN10300_PLT32                15
+#define R_MN10300_PLT16                16
+#define R_MN10300_GOT32                17
+#define R_MN10300_GOT24                18
+#define R_MN10300_GOT16                19
+#define R_MN10300_COPY         20
+#define R_MN10300_GLOB_DAT     21
+#define R_MN10300_JMP_SLOT     22
+#define R_MN10300_RELATIVE     23
+
+#define R_MN10300_NUM          24
+
+
+
+#define R_M32R_NONE            0
+#define R_M32R_16              1
+#define R_M32R_32              2
+#define R_M32R_24              3
+#define R_M32R_10_PCREL                4
+#define R_M32R_18_PCREL                5
+#define R_M32R_26_PCREL                6
+#define R_M32R_HI16_ULO                7
+#define R_M32R_HI16_SLO                8
+#define R_M32R_LO16            9
+#define R_M32R_SDA16           10
+#define R_M32R_GNU_VTINHERIT   11
+#define R_M32R_GNU_VTENTRY     12
+
+#define R_M32R_16_RELA         33
+#define R_M32R_32_RELA         34
+#define R_M32R_24_RELA         35
+#define R_M32R_10_PCREL_RELA   36
+#define R_M32R_18_PCREL_RELA   37
+#define R_M32R_26_PCREL_RELA   38
+#define R_M32R_HI16_ULO_RELA   39
+#define R_M32R_HI16_SLO_RELA   40
+#define R_M32R_LO16_RELA       41
+#define R_M32R_SDA16_RELA      42
+#define R_M32R_RELA_GNU_VTINHERIT      43
+#define R_M32R_RELA_GNU_VTENTRY        44
+#define R_M32R_REL32           45
+
+#define R_M32R_GOT24           48
+#define R_M32R_26_PLTREL       49
+#define R_M32R_COPY            50
+#define R_M32R_GLOB_DAT                51
+#define R_M32R_JMP_SLOT                52
+#define R_M32R_RELATIVE                53
+#define R_M32R_GOTOFF          54
+#define R_M32R_GOTPC24         55
+#define R_M32R_GOT16_HI_ULO    56
+
+#define R_M32R_GOT16_HI_SLO    57
+
+#define R_M32R_GOT16_LO                58
+#define R_M32R_GOTPC_HI_ULO    59
+
+#define R_M32R_GOTPC_HI_SLO    60
+
+#define R_M32R_GOTPC_LO                61
+
+#define R_M32R_GOTOFF_HI_ULO   62
+
+#define R_M32R_GOTOFF_HI_SLO   63
+
+#define R_M32R_GOTOFF_LO       64
+#define R_M32R_NUM             256
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/include/endian.h b/include/endian.h
new file mode 100644 (file)
index 0000000..bcf6766
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _ENDIAN_H
+#define _ENDIAN_H
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
+
+#include <bits/endian.h>
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define BIG_ENDIAN __BIG_ENDIAN
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+#define PDP_ENDIAN __PDP_ENDIAN
+#define BYTE_ORDER __BYTE_ORDER
+#endif
+
+#endif
diff --git a/include/errno.h b/include/errno.h
new file mode 100644 (file)
index 0000000..d9c2c9c
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef        _ERRNO_H
+#define _ERRNO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bits/errno.h>
+
+extern int *__errno_location(void);
+#define errno (*__errno_location())
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/fcntl.h b/include/fcntl.h
new file mode 100644 (file)
index 0000000..61a6cb5
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef        _FCNTL_H
+#define        _FCNTL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_off_t
+#define __NEED_pid_t
+#define __NEED_mode_t
+
+#include <bits/alltypes.h>
+
+#include <bits/fcntl.h>
+
+struct flock
+{
+       short l_type;
+       short l_whence;
+       off_t l_start;
+       off_t l_len;
+       pid_t l_pid;
+};
+
+int creat(const char *, mode_t);
+int fcntl(int, int, ...);
+int open(const char *, int, ...);
+int openat(int, const char *, int, ...);
+int posix_fadvise(int, off_t, off_t, int);
+int posix_fallocate(int, off_t, off_t);
+
+#undef SEEK_SET
+#undef SEEK_CUR
+#undef SEEK_END
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/features.h b/include/features.h
new file mode 100644 (file)
index 0000000..851afb6
--- /dev/null
@@ -0,0 +1 @@
+#warning "features.h is bogus"
diff --git a/include/fenv.h b/include/fenv.h
new file mode 100644 (file)
index 0000000..05de990
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _FENV_H
+#define _FENV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bits/fenv.h>
+
+int feclearexcept(int);
+int fegetexceptflag(fexcept_t *, int);
+int feraiseexcept(int);
+int fesetexceptflag(const fexcept_t *, int);
+int fetestexcept(int);
+
+int fegetround(void);
+int fesetround(int);
+
+int fegetenv(fenv_t *);
+int feholdexcept(fenv_t *);
+int fesetenv(const fenv_t *);
+int feupdateenv(const fenv_t *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/include/float.h b/include/float.h
new file mode 100644 (file)
index 0000000..ef91f37
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _FLOAT_H
+#define _FLOAT_H
+
+#define FLT_RADIX 2
+
+#define FLT_MIN 1.17549435e-38F
+#define FLT_MAX 3.40282347e+38F
+#define FLT_EPSILON 1.19209290e-07F
+
+#define FLT_MANT_DIG 24
+#define FLT_MIN_EXP (-125)
+#define FLT_MAX_EXP 128
+
+#define FLT_DIG 6
+#define FLT_MIN_10_EXP (-37)
+#define FLT_MAX_10_EXP 38
+
+#define DBL_MIN 2.2250738585072014e-308
+#define DBL_MAX 1.7976931348623157e+308
+#define DBL_EPSILON 2.2204460492503131e-16
+
+#define DBL_MANT_DIG 53
+#define DBL_MIN_EXP (-1021)
+#define DBL_MAX_EXP 1024
+
+#define DBL_DIG 15
+#define DBL_MIN_10_EXP (-307)
+#define DBL_MAX_10_EXP 308
+
+#include <bits/float.h>
+
+#define DECIMAL_DIG LDBL_DIG
+
+#endif
diff --git a/include/fnmatch.h b/include/fnmatch.h
new file mode 100644 (file)
index 0000000..b7aee50
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef        _FNMATCH_H
+#define        _FNMATCH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        FNM_PATHNAME 0x1
+#define        FNM_NOESCAPE 0x2
+#define        FNM_PERIOD   0x4
+
+#ifdef _GNU_SOURCE
+#define        FNM_CASEFOLD 0x10
+#endif
+
+#define        FNM_NOMATCH 1
+#define FNM_NOSYS   (-1)
+
+int fnmatch(const char *, const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/ftw.h b/include/ftw.h
new file mode 100644 (file)
index 0000000..8d31c6d
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _FTW_H
+#define        _FTW_H
+
+/* Normally we do not nest header includes. However useless bloat
+ * like ftw may be treated as a special case. Otherwise we would
+ * have to deal with duplicating all the stat.h mess. */
+#include <sys/stat.h>
+
+#define FTW_F   1
+#define FTW_D   2
+#define FTW_DNR 3
+#define FTW_NS  4
+#define FTW_SL  5
+#define FTW_DP  6
+#define FTW_SLN 7
+
+#define FTW_PHYS  1
+#define FTW_MOUNT 2
+#define FTW_CHDIR 4
+#define FTW_DEPTH 8
+
+struct FTW
+{
+       int base;
+       int level;
+};
+
+int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
+int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int);
+
+#endif
diff --git a/include/getopt.h b/include/getopt.h
new file mode 100644 (file)
index 0000000..0de05ae
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int getopt(int, char * const [], const char *);
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+#ifdef _GNU_SOURCE
+struct option
+{
+       const char *name;
+       int has_arg;
+       int *flag;
+       int val;
+};
+
+int getopt_long(int, char *const *, const char *, const struct option *, int *);
+int getopt_long_only(int, char *const *, const char *, const struct option *, int *);
+
+#define no_argument        0
+#define required_argument  1
+#define optional_argument  2
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/glob.h b/include/glob.h
new file mode 100644 (file)
index 0000000..185912d
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef        _GLOB_H
+#define        _GLOB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+typedef struct {
+       size_t gl_pathc;
+       char **gl_pathv;
+       size_t gl_offs;
+       int __dummy1;
+       void *__dummy2[5];
+} glob_t;
+
+int  glob(const char *, int, int (*)(const char *, int), glob_t *);
+void globfree(glob_t *);
+
+#define GLOB_ERR      0x01
+#define GLOB_MARK     0x02
+#define GLOB_NOSORT   0x04
+#define GLOB_DOOFFS   0x08
+#define GLOB_NOCHECK  0x10
+#define GLOB_APPEND   0x20
+#define GLOB_NOESCAPE 0x40
+#define        GLOB_PERIOD   0x80
+
+#define GLOB_NOSPACE 1
+#define GLOB_ABORTED 2
+#define GLOB_NOMATCH 3
+#define GLOB_NOSYS   4
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/grp.h b/include/grp.h
new file mode 100644 (file)
index 0000000..d4a3526
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef        _GRP_H
+#define        _GRP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+#define __NEED_gid_t
+
+#include <bits/alltypes.h>
+
+struct group
+{
+       char *gr_name;
+       char *gr_passwd;
+       gid_t gr_gid;
+       char **gr_mem;
+};
+
+struct group  *getgrgid(gid_t);
+struct group  *getgrnam(const char *);
+
+int getgrgid_r(gid_t, struct group *, char *, size_t, struct group **);
+int getgrnam_r(const char *, struct group *, char *, size_t, struct group **);
+
+struct group  *getgrent(void);
+void           endgrent(void);
+void           setgrent(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/iconv.h b/include/iconv.h
new file mode 100644 (file)
index 0000000..f2ccaf8
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _ICONV_H
+#define _ICONV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+typedef void *iconv_t;
+
+iconv_t iconv_open(const char *, const char *);
+size_t iconv(iconv_t, char **, size_t *, char **, size_t *);
+int iconv_close(iconv_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/inttypes.h b/include/inttypes.h
new file mode 100644 (file)
index 0000000..13ba6e0
--- /dev/null
@@ -0,0 +1,227 @@
+#ifndef _INTTYPES_H
+#define _INTTYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define __NEED_wchar_t
+#include <bits/alltypes.h>
+
+typedef struct { intmax_t quot, rem; } imaxdiv_t;
+
+intmax_t imaxabs(intmax_t);
+imaxdiv_t imaxdiv(intmax_t, intmax_t);
+
+intmax_t strtoimax(const char *, char **, int);
+uintmax_t strtoumax(const char *, char **, int);
+
+intmax_t wcstoimax(const wchar_t *, wchar_t **, int);
+uintmax_t wcstoumax(const wchar_t *, wchar_t **, int);
+
+#if !defined __cplusplus || defined __STDC_FORMAT_MACROS
+
+#define __PRI64  "ll"
+#define __PRIPTR "l"
+
+#define PRId8  "d"
+#define PRId16 "d"
+#define PRId32 "d"
+#define PRId64 __PRI64 "d"
+
+#define PRIdLEAST8  "d"
+#define PRIdLEAST16 "d"
+#define PRIdLEAST32 "d"
+#define PRIdLEAST64 __PRI64 "d"
+
+#define PRIdFAST8  "d"
+#define PRIdFAST16 "d"
+#define PRIdFAST32 "d"
+#define PRIdFAST64 __PRI64 "d"
+
+#define PRIi8  "i"
+#define PRIi16 "i"
+#define PRIi32 "i"
+#define PRIi64 __PRI64 "i"
+
+#define PRIiLEAST8  "i"
+#define PRIiLEAST16 "i"
+#define PRIiLEAST32 "i"
+#define PRIiLEAST64 __PRI64 "i"
+
+#define PRIiFAST8  "i"
+#define PRIiFAST16 "i"
+#define PRIiFAST32 "i"
+#define PRIiFAST64 __PRI64 "i"
+
+#define PRIo8  "o"
+#define PRIo16 "o"
+#define PRIo32 "o"
+#define PRIo64 __PRI64 "o"
+
+#define PRIoLEAST8  "o"
+#define PRIoLEAST16 "o"
+#define PRIoLEAST32 "o"
+#define PRIoLEAST64 __PRI64 "o"
+
+#define PRIoFAST8  "o"
+#define PRIoFAST16 "o"
+#define PRIoFAST32 "o"
+#define PRIoFAST64 __PRI64 "o"
+
+#define PRIu8  "u"
+#define PRIu16 "u"
+#define PRIu32 "u"
+#define PRIu64 __PRI64 "u"
+
+#define PRIuLEAST8  "u"
+#define PRIuLEAST16 "u"
+#define PRIuLEAST32 "u"
+#define PRIuLEAST64 __PRI64 "u"
+
+#define PRIuFAST8  "u"
+#define PRIuFAST16 "u"
+#define PRIuFAST32 "u"
+#define PRIuFAST64 __PRI64 "u"
+
+#define PRIx8  "x"
+#define PRIx16 "x"
+#define PRIx32 "x"
+#define PRIx64 __PRI64 "x"
+
+#define PRIxLEAST8  "x"
+#define PRIxLEAST16 "x"
+#define PRIxLEAST32 "x"
+#define PRIxLEAST64 __PRI64 "x"
+
+#define PRIxFAST8  "x"
+#define PRIxFAST16 "x"
+#define PRIxFAST32 "x"
+#define PRIxFAST64 __PRI64 "x"
+
+#define PRIX8  "X"
+#define PRIX16 "X"
+#define PRIX32 "X"
+#define PRIX64 __PRI64 "X"
+
+#define PRIXLEAST8  "X"
+#define PRIXLEAST16 "X"
+#define PRIXLEAST32 "X"
+#define PRIXLEAST64 __PRI64 "X"
+
+#define PRIXFAST8  "X"
+#define PRIXFAST16 "X"
+#define PRIXFAST32 "X"
+#define PRIXFAST64 __PRI64 "X"
+
+#define PRIdMAX __PRI64 "d"
+#define PRIiMAX __PRI64 "i"
+#define PRIoMAX __PRI64 "o"
+#define PRIuMAX __PRI64 "u"
+#define PRIxMAX __PRI64 "x"
+#define PRIXMAX __PRI64 "X"
+
+#define PRIdPTR __PRIPTR "d"
+#define PRIiPTR __PRIPTR "i"
+#define PRIoPTR __PRIPTR "o"
+#define PRIuPTR __PRIPTR "u"
+#define PRIxPTR __PRIPTR "x"
+#define PRIXPTR __PRIPTR "X"
+
+#define SCNd8   "hhd"
+#define SCNd16  "hd"
+#define SCNd32  "d"
+#define SCNd64  __PRI64 "d"
+
+#define SCNdLEAST8  "hhd"
+#define SCNdLEAST16 "hd"
+#define SCNdLEAST32 "d"
+#define SCNdLEAST64 __PRI64 "d"
+
+#define SCNdFAST8  "hhd"
+#define SCNdFAST16 __PRIPTR "d"
+#define SCNdFAST32 __PRIPTR "d"
+#define SCNdFAST64 __PRI64 "d"
+
+#define SCNi8   "hhi"
+#define SCNi16  "hi"
+#define SCNi32  "i"
+#define SCNi64  __PRI64 "i"
+
+#define SCNiLEAST8  "hhi"
+#define SCNiLEAST16 "hi"
+#define SCNiLEAST32 "i"
+#define SCNiLEAST64 __PRI64 "i"
+
+#define SCNiFAST8  "hhi"
+#define SCNiFAST16 __PRIPTR "i"
+#define SCNiFAST32 __PRIPTR "i"
+#define SCNiFAST64 __PRI64 "i"
+
+#define SCNu8   "hhu"
+#define SCNu16  "hu"
+#define SCNu32  "u"
+#define SCNu64  __PRI64 "u"
+
+#define SCNuLEAST8  "hhu"
+#define SCNuLEAST16 "hu"
+#define SCNuLEAST32 "u"
+#define SCNuLEAST64 __PRI64 "u"
+
+#define SCNuFAST8 "hhu"
+#define SCNuFAST16 __PRIPTR "u"
+#define SCNuFAST32 __PRIPTR "u"
+#define SCNuFAST64 __PRI64 "u"
+
+#define SCNo8   "hho"
+#define SCNo16  "ho"
+#define SCNo32  "o"
+#define SCNo64  __PRI64 "o"
+
+#define SCNoLEAST8  "hho"
+#define SCNoLEAST16 "ho"
+#define SCNoLEAST32 "o"
+#define SCNoLEAST64 __PRI64 "o"
+
+#define SCNoFAST8  "hho"
+#define SCNoFAST16 __PRIPTR "o"
+#define SCNoFAST32 __PRIPTR "o"
+#define SCNoFAST64 __PRI64 "o"
+
+#define SCNx8   "hhx"
+#define SCNx16  "hx"
+#define SCNx32  "x"
+#define SCNx64  __PRI64 "x"
+
+#define SCNxLEAST8  "hhx"
+#define SCNxLEAST16 "hx"
+#define SCNxLEAST32 "x"
+#define SCNxLEAST64 __PRI64 "x"
+
+#define SCNxFAST8  "hhx"
+#define SCNxFAST16 __PRIPTR "x"
+#define SCNxFAST32 __PRIPTR "x"
+#define SCNxFAST64 __PRI64 "x"
+
+#define SCNdMAX __PRI64 "d"
+#define SCNiMAX __PRI64 "i"
+#define SCNoMAX __PRI64 "o"
+#define SCNuMAX __PRI64 "u"
+#define SCNxMAX __PRI64 "x"
+
+#define SCNdPTR __PRIPTR "d"
+#define SCNiPTR __PRIPTR "i"
+#define SCNoPTR __PRIPTR "o"
+#define SCNuPTR __PRIPTR "u"
+#define SCNxPTR __PRIPTR "x"
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/langinfo.h b/include/langinfo.h
new file mode 100644 (file)
index 0000000..4d9e099
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef _LANGINFO_H
+#define _LANGINFO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_nl_item
+
+#include <bits/alltypes.h>
+
+#define ABDAY_1 0x20000
+#define ABDAY_2 0x20001
+#define ABDAY_3 0x20002
+#define ABDAY_4 0x20003
+#define ABDAY_5 0x20004
+#define ABDAY_6 0x20005
+#define ABDAY_7 0x20006
+
+#define DAY_1 0x20007
+#define DAY_2 0x20008
+#define DAY_3 0x20009
+#define DAY_4 0x2000A
+#define DAY_5 0x2000B
+#define DAY_6 0x2000C
+#define DAY_7 0x2000D
+
+#define ABMON_1 0x2000E
+#define ABMON_2 0x2000F
+#define ABMON_3 0x20010
+#define ABMON_4 0x20011
+#define ABMON_5 0x20012
+#define ABMON_6 0x20013
+#define ABMON_7 0x20014
+#define ABMON_8 0x20015
+#define ABMON_9 0x20016
+#define ABMON_10 0x20017
+#define ABMON_11 0x20018
+#define ABMON_12 0x20019
+
+#define MON_1 0x2001A
+#define MON_2 0x2001B
+#define MON_3 0x2001C
+#define MON_4 0x2001D
+#define MON_5 0x2001E
+#define MON_6 0x2001F
+#define MON_7 0x20020
+#define MON_8 0x20021
+#define MON_9 0x20022
+#define MON_10 0x20023
+#define MON_11 0x20024
+#define MON_12 0x20025
+
+#define AM_STR 0x20026
+#define PM_STR 0x20027
+
+#define D_T_FMT 0x20028
+#define D_FMT 0x20029
+#define T_FMT 0x2002A
+#define T_FMT_AMPM 0x2002B
+
+#define ERA 0x2002C
+#define ERA_D_FMT 0x2002E
+#define ALT_DIGITS 0x2002F
+#define ERA_D_T_FMT 0x20030
+#define ERA_T_FMT 0x20031
+
+#define CODESET 14
+
+#define CRNCYSTR 0x4000F
+
+#define RADIXCHAR 0x10000
+#define THOUSEP 0x10001
+#define YESEXPR 0x50000
+#define NOEXPR 0x50001
+#define YESSTR 0x50002
+#define NOSTR 0x50003
+
+char *nl_langinfo(nl_item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/libgen.h b/include/libgen.h
new file mode 100644 (file)
index 0000000..7c7fd9c
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _LIBGEN_H
+#define _LIBGEN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *dirname(char *);
+char *basename(char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/libintl.h b/include/libintl.h
new file mode 100644 (file)
index 0000000..a2dada6
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _LIBINTL_H
+#define _LIBINTL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __USE_GNU_GETTEXT 1
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 1 : -1)
+
+char *gettext(const char *);
+char *dgettext(const char *, const char *);
+char *dcgettext(const char *, const char *, int);
+char *ngettext(const char *, const char *, unsigned long);
+char *dngettext(const char *, const char *, const char *, unsigned long);
+char *dcngettext(const char *, const char *, const char *, unsigned long, int);
+char *textdomain(const char *);
+char *bindtextdomain (const char *, const char *);
+char *bind_textdomain_codeset(const char *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/limits.h b/include/limits.h
new file mode 100644 (file)
index 0000000..4499afb
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+/* Most limits are system-specific */
+
+#include <bits/limits.h>
+
+/* Some universal constants... */
+
+#define CHAR_BIT 8
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+#define UCHAR_MAX 255
+#define CHAR_MIN (-128)
+#define CHAR_MAX 127
+#define SSIZE_MAX LONG_MAX
+
+#define MB_LEN_MAX 4
+#define TZNAME_MAX 6
+#define TTY_NAME_MAX 20
+#define HOST_NAME_MAX 255
+
+/* Implementation choices... */
+
+#define PTHREAD_KEYS_MAX  1024
+#define PTHREAD_STACK_MIN (2*PAGE_SIZE)
+
+/* Arbitrary numbers... */
+
+#define BC_BASE_MAX 99
+#define BC_DIM_MAX 2048
+#define BC_SCALE_MAX 99
+#define BC_STRING_MAX 1000
+#define CHARCLASS_NAME_MAX 14
+#define COLL_WEIGHTS_MAX 2
+#define EXPR_NEST_MAX 32
+#define LINE_MAX 4096
+#define RE_DUP_MAX 255
+
+#define NL_ARGMAX 9
+#define NL_LANGMAX 32
+#define NL_MSGMAX 32767
+#define NL_NMAX (MB_LEN_MAX*4)
+#define NL_SETMAX 255
+#define NL_TEXTMAX 2048
+
+/* POSIX/SUS requirements follow. These numbers come directly
+ * from SUS and have nothing to do with the host system. */
+
+#define _POSIX_AIO_LISTIO_MAX   2
+#define _POSIX_AIO_MAX          1
+#define _POSIX_ARG_MAX          4096
+#define _POSIX_CHILD_MAX        25
+#define _POSIX_DELAYTIMER_MAX   32
+#define _POSIX_HOST_NAME_MAX    255
+#define _POSIX_LINK_MAX         8
+#define _POSIX_LOGIN_NAME_MAX   9
+#define _POSIX_MAX_CANON        255
+#define _POSIX_MAX_INPUT        255
+#define _POSIX_MQ_OPEN_MAX      8
+#define _POSIX_MQ_PRIO_MAX      32
+#define _POSIX_NAME_MAX         14
+#define _POSIX_NGROUPS_MAX      8
+#define _POSIX_OPEN_MAX         20
+#define _POSIX_PATH_MAX         256
+#define _POSIX_PIPE_BUF         512
+#define _POSIX_RE_DUP_MAX       255
+#define _POSIX_RTSIG_MAX        8
+#define _POSIX_SEM_NSEMS_MAX    256
+#define _POSIX_SEM_VALUE_MAX    32767
+#define _POSIX_SIGQUEUE_MAX     32
+#define _POSIX_SSIZE_MAX        32767
+#define _POSIX_STREAM_MAX       8
+#define _POSIX_SS_REPL_MAX      4
+#define _POSIX_SYMLINK_MAX      255
+#define _POSIX_SYMLOOP_MAX      8
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+#define _POSIX_THREAD_KEYS_MAX  128
+#define _POSIX_THREAD_THREADS_MAX 64
+#define _POSIX_TIMER_MAX        32
+#define _POSIX_TRACE_EVENT_NAME_MAX 30
+#define _POSIX_TRACE_NAME_MAX   8
+#define _POSIX_TRACE_SYS_MAX    8
+#define _POSIX_TRACE_USER_EVENT_MAX 32
+#define _POSIX_TTY_NAME_MAX     9
+#define _POSIX_TZNAME_MAX       6
+#define _POSIX2_BC_BASE_MAX     99
+#define _POSIX2_BC_DIM_MAX      2048
+#define _POSIX2_BC_SCALE_MAX    99
+#define _POSIX2_BC_STRING_MAX   1000
+#define _POSIX2_CHARCLASS_NAME_MAX 14
+#define _POSIX2_COLL_WEIGHTS_MAX 2
+#define _POSIX2_EXPR_NEST_MAX   32
+#define _POSIX2_LINE_MAX        2048
+#define _POSIX2_RE_DUP_MAX      255
+
+#define _XOPEN_IOV_MAX          16
+#define _XOPEN_NAME_MAX         255
+#define _XOPEN_PATH_MAX         1024
+
+#endif
diff --git a/include/linux/loop.h b/include/linux/loop.h
new file mode 100644 (file)
index 0000000..41aad40
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef _LINUX_LOOP_H
+#define _LINUX_LOOP_H
+
+#include <stdint.h>
+
+#define LO_NAME_SIZE   64
+#define LO_KEY_SIZE    32
+
+enum {
+       LO_FLAGS_READ_ONLY      = 1,
+       LO_FLAGS_USE_AOPS       = 2,
+       LO_FLAGS_AUTOCLEAR      = 4,
+};
+
+struct loop_info {
+       int                lo_number;
+       long               lo_device;
+       unsigned long      lo_inode;
+       long               lo_rdevice;
+       int                lo_offset;
+       int                lo_encrypt_type;
+       int                lo_encrypt_key_size;
+       int                lo_flags;
+       char               lo_name[LO_NAME_SIZE];
+       unsigned char      lo_encrypt_key[LO_KEY_SIZE];
+       unsigned long      lo_init[2];
+       char               reserved[4];
+};
+
+struct loop_info64 {
+       uint64_t           lo_device;
+       uint64_t           lo_inode;
+       uint64_t           lo_rdevice;
+       uint64_t           lo_offset;
+       uint64_t           lo_sizelimit;
+       uint32_t           lo_number;
+       uint32_t           lo_encrypt_type;
+       uint32_t           lo_encrypt_key_size;
+       uint32_t           lo_flags;
+       uint8_t            lo_file_name[LO_NAME_SIZE];
+       uint8_t            lo_crypt_name[LO_NAME_SIZE];
+       uint8_t            lo_encrypt_key[LO_KEY_SIZE];
+       uint64_t           lo_init[2];
+};
+
+
+#define LO_CRYPT_NONE          0
+#define LO_CRYPT_XOR           1
+#define LO_CRYPT_DES           2
+#define LO_CRYPT_FISH2         3
+#define LO_CRYPT_BLOW          4
+#define LO_CRYPT_CAST128       5
+#define LO_CRYPT_IDEA          6
+#define LO_CRYPT_DUMMY         9
+#define LO_CRYPT_SKIPJACK      10
+#define LO_CRYPT_CRYPTOAPI     18
+#define MAX_LO_CRYPT           20
+
+
+#define LOOP_SET_FD            0x4C00
+#define LOOP_CLR_FD            0x4C01
+#define LOOP_SET_STATUS                0x4C02
+#define LOOP_GET_STATUS                0x4C03
+#define LOOP_SET_STATUS64      0x4C04
+#define LOOP_GET_STATUS64      0x4C05
+#define LOOP_CHANGE_FD         0x4C06
+#define LOOP_SET_CAPACITY      0x4C07
+
+#endif
diff --git a/include/linux/version.h b/include/linux/version.h
new file mode 100644 (file)
index 0000000..e6a89ef
--- /dev/null
@@ -0,0 +1,2 @@
+#define LINUX_VERSION_CODE 132638
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/include/locale.h b/include/locale.h
new file mode 100644 (file)
index 0000000..7023023
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef        _LOCALE_H
+#define        _LOCALE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+#define LC_CTYPE    0
+#define LC_NUMERIC  1
+#define LC_TIME     2
+#define LC_COLLATE  3
+#define LC_MONETARY 4
+#define LC_MESSAGES 5
+#define LC_ALL      6
+
+struct lconv {
+       char *decimal_point;
+       char *thousands_sep;
+       char *grouping;
+
+       char *int_curr_symbol;
+       char *currency_symbol;
+       char *mon_decimal_point;
+       char *mon_thousands_sep;
+       char *mon_grouping;
+       char *positive_sign;
+       char *negative_sign;
+       char int_frac_digits;
+       char frac_digits;
+       char p_cs_precedes;
+       char p_sep_by_space;
+       char n_cs_precedes;
+       char n_sep_by_space;
+       char p_sign_posn;
+       char n_sign_posn;
+       char int_p_cs_precedes;
+       char int_p_sep_by_space;
+       char int_n_cs_precedes;
+       char int_n_sep_by_space;
+       char int_p_sign_posn;
+       char int_n_sign_posn;
+};
+
+
+char *setlocale (int, const char *);
+struct lconv *localeconv(void);
+
+
+#if 1
+
+#define __NEED_locale_t
+
+#include <bits/alltypes.h>
+
+#define LC_GLOBAL_LOCALE ((locale_t)-1)
+
+#define LC_CTYPE_MASK    (1<<LC_CTYPE)
+#define LC_NUMERIC_MASK  (1<<LC_NUMERIC)
+#define LC_TIME_MASK     (1<<LC_TIME)
+#define LC_COLLATE_MASK  (1<<LC_COLLATE)
+#define LC_MONETARY_MASK (1<<LC_MONETARY)
+#define LC_MESSAGES_MASK (1<<LC_MESSAGES)
+#define LC_ALL_MASK      0x7fffffff
+
+locale_t duplocale(locale_t);
+void freelocale(locale_t);
+locale_t newlocale(int, const char *, locale_t);
+locale_t uselocale(locale_t);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/malloc.h b/include/malloc.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/math.h b/include/math.h
new file mode 100644 (file)
index 0000000..cc9befb
--- /dev/null
@@ -0,0 +1,300 @@
+#ifndef _MATH_H
+#define _MATH_H
+
+#define __NEED___uint16_t
+#define __NEED___uint32_t
+#define __NEED___uint64_t
+#include <bits/alltypes.h>
+
+#define M_E             2.7182818284590452354   /* e */
+#define M_LOG2E         1.4426950408889634074   /* log_2 e */
+#define M_LOG10E        0.43429448190325182765  /* log_10 e */
+#define M_LN2           0.69314718055994530942  /* log_e 2 */
+#define M_LN10          2.30258509299404568402  /* log_e 10 */
+#define M_PI            3.14159265358979323846  /* pi */
+#define M_PI_2          1.57079632679489661923  /* pi/2 */
+#define M_PI_4          0.78539816339744830962  /* pi/4 */
+#define M_1_PI          0.31830988618379067154  /* 1/pi */
+#define M_2_PI          0.63661977236758134308  /* 2/pi */
+#define M_2_SQRTPI      1.12837916709551257390  /* 2/sqrt(pi) */
+#define M_SQRT2         1.41421356237309504880  /* sqrt(2) */
+#define M_SQRT1_2       0.70710678118654752440  /* 1/sqrt(2) */
+
+#define __MAKE_FLOAT(i) (((union { int __i; float __f; }){ .__i = i }).__f)
+
+#define NAN       __MAKE_FLOAT(0x7fc00000)
+#define INFINITY  __MAKE_FLOAT(0x7f800000)
+
+#define HUGE_VALF INFINITY
+#define HUGE_VAL  ((double)INFINITY)
+#define HUGE_VALL ((long double)INFINITY)
+
+#define MAXFLOAT  __MAKE_FLOAT(0x7f7fffff)
+
+#define MATH_ERRNO  1
+#define MATH_EXCEPT 2
+#define math_errhandling 2
+
+#define FP_ILOGBNAN (((unsigned)-1)>>1)
+#define FP_ILOGB0 (~FP_ILOGBNAN)
+
+#define FP_NAN       0
+#define FP_INFINITE  1
+#define FP_ZERO      2
+#define FP_SUBNORMAL 3
+#define FP_NORMAL    4
+
+int __fpclassifyf(float);
+int __fpclassify(double);
+int __fpclassifyl(long double);
+
+#define fpclassify(x) ( \
+       sizeof(x) == sizeof(float) ? __fpclassifyf(x) : \
+       sizeof(x) == sizeof(double) ? __fpclassify(x) : \
+       __fpclassifyl(x) )
+
+#define isinf(x)    (fpclassify(x) == FP_INFINITE)
+#define isnan(x)    (fpclassify(x) == FP_NAN)
+#define isnormal(x) (fpclassify(x) == FP_NORMAL)
+#define isfinite(x) (fpclassify(x) > FP_INFINITE)
+
+double      acos(double);
+float       acosf(float);
+long double acosl(long double);
+
+double      acosh(double);
+float       acoshf(float);
+long double acoshl(long double);
+
+double      asin(double);
+float       asinf(float);
+long double asinl(long double);
+
+double      asinh(double);
+float       asinhf(float);
+long double asinhl(long double);
+
+double      atan(double);
+float       atanf(float);
+long double atanl(long double);
+
+double      atan2(double, double);
+float       atan2f(float, float);
+long double atan2l(long double, long double);
+
+double      atanh(double);
+float       atanhf(float);
+long double atanhl(long double);
+
+double      cbrt(double);
+float       cbrtf(float);
+long double cbrtl(long double);
+
+double      ceil(double);
+float       ceilf(float);
+long double ceill(long double);
+
+double      copysign(double, double);
+float       copysignf(float, float);
+long double copysignl(long double, long double);
+
+double      cos(double);
+float       cosf(float);
+long double cosl(long double);
+
+double      cosh(double);
+float       coshf(float);
+long double coshl(long double);
+
+double      erf(double);
+float       erff(float);
+long double erfl(long double);
+
+double      erfc(double);
+float       erfcf(float);
+long double erfcl(long double);
+
+double      exp(double);
+float       expf(float);
+long double expl(long double);
+
+double      exp2(double);
+float       exp2f(float);
+long double exp2l(long double);
+
+double      expm1(double);
+float       expm1f(float);
+long double expm1l(long double);
+
+double      fabs(double);
+float       fabsf(float);
+long double fabsl(long double);
+
+double      fdim(double, double);
+float       fdimf(float, float);
+long double fdiml(long double, long double);
+
+double      floor(double);
+float       floorf(float);
+long double floorl(long double);
+
+double      fma(double, double, double);
+float       fmaf(float, float, float);
+long double fmal(long double, long double, long double);
+
+double      fmax(double, double);
+float       fmaxf(float, float);
+long double fmaxl(long double, long double);
+
+double      fmin(double, double);
+float       fminf(float, float);
+long double fminl(long double, long double);
+
+double      fmod(double, double);
+float       fmodf(float, float);
+long double fmodl(long double, long double);
+
+double      frexp(double, int *);
+float       frexpf(float value, int *);
+long double frexpl(long double value, int *);
+
+double      hypot(double, double);
+float       hypotf(float, float);
+long double hypotl(long double, long double);
+
+int         ilogb(double);
+int         ilogbf(float);
+int         ilogbl(long double);
+
+double      ldexp(double, int);
+float       ldexpf(float, int);
+long double ldexpl(long double, int);
+
+double      lgamma(double);
+float       lgammaf(float);
+long double lgammal(long double);
+
+long long   llrint(double);
+long long   llrintf(float);
+long long   llrintl(long double);
+
+long long   llround(double);
+long long   llroundf(float);
+long long   llroundl(long double);
+
+double      log(double);
+float       logf(float);
+long double logl(long double);
+
+double      log10(double);
+float       log10f(float);
+long double log10l(long double);
+
+double      log1p(double);
+float       log1pf(float);
+long double log1pl(long double);
+
+double      log2(double);
+float       log2f(float);
+long double log2l(long double);
+
+double      logb(double);
+float       logbf(float);
+long double logbl(long double);
+
+long        lrint(double);
+long        lrintf(float);
+long        lrintl(long double);
+
+long        lround(double);
+long        lroundf(float);
+long        lroundl(long double);
+
+double      modf(double, double *);
+float       modff(float, float *);
+long double modfl(long double, long double *);
+
+double      nan(const char *);
+float       nanf(const char *);
+long double nanl(const char *);
+
+double      nearbyint(double);
+float       nearbyintf(float);
+long double nearbyintl(long double);
+
+double      nextafter(double, double);
+float       nextafterf(float, float);
+long double nextafterl(long double, long double);
+
+double      nexttoward(double, long double);
+float       nexttowardf(float, long double);
+long double nexttowardl(long double, long double);
+
+double      pow(double, double);
+float       powf(float, float);
+long double powl(long double, long double);
+
+double      remainder(double, double);
+float       remainderf(float, float);
+long double remainderl(long double, long double);
+
+double      remquo(double, double, int *);
+float       remquof(float, float, int *);
+long double remquol(long double, long double, int *);
+
+double      rint(double);
+float       rintf(float);
+long double rintl(long double);
+
+double      round(double);
+float       roundf(float);
+long double roundl(long double);
+
+double      scalbln(double, long);
+float       scalblnf(float, long);
+long double scalblnl(long double, long);
+
+double      scalbn(double, int);
+float       scalbnf(float, int);
+long double scalbnl(long double, int);
+
+double      sin(double);
+float       sinf(float);
+long double sinl(long double);
+
+double      sinh(double);
+float       sinhf(float);
+long double sinhl(long double);
+
+double      sqrt(double);
+float       sqrtf(float);
+long double sqrtl(long double);
+
+double      tan(double);
+float       tanf(float);
+long double tanl(long double);
+
+double      tanh(double);
+float       tanhf(float);
+long double tanhl(long double);
+
+double      tgamma(double);
+float       tgammaf(float);
+long double tgammal(long double);
+
+double      trunc(double);
+float       truncf(float);
+long double truncl(long double);
+
+/* XSI stuff */
+double      j0(double);
+double      j1(double);
+double      jn(int, double);
+double      scalb(double, double);
+double      y0(double);
+double      y1(double);
+double      yn(int, double);
+
+extern int signgam;
+
+#endif
diff --git a/include/mntent.h b/include/mntent.h
new file mode 100644 (file)
index 0000000..c0fed7f
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _MNTENT_H
+#define _MNTENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_FILE
+#include <bits/alltypes.h>
+
+#define MOUNTED "/etc/mtab"
+
+#define MNTTYPE_IGNORE "ignore"
+#define MNTTYPE_NFS    "nfs"
+#define MNTTYPE_SWAP   "swap"
+#define MNTOPT_DEFAULTS        "defaults"
+#define MNTOPT_RO      "ro"
+#define MNTOPT_RW      "rw"
+#define MNTOPT_SUID    "suid"
+#define MNTOPT_NOSUID  "nosuid"
+#define MNTOPT_NOAUTO  "noauto"
+
+struct mntent
+{
+       char *mnt_fsname;
+       char *mnt_dir;
+       char *mnt_type;
+       char *mnt_opts;
+       int mnt_freq;
+       int mnt_passno;
+};
+
+FILE *setmntent(const char *, const char *);
+int endmntent(FILE *);
+struct mntent *getmntent(FILE *);
+int addmntent(FILE *, const struct mntent *);
+char *hasmntopt(const struct mntent *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/net/ethernet.h b/include/net/ethernet.h
new file mode 100644 (file)
index 0000000..a536502
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __NET_ETHERNET_H
+#define __NET_ETHERNET_H 1
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <netinet/if_ether.h>
+
+struct ether_addr {
+       uint8_t ether_addr_octet[ETH_ALEN];
+};
+
+struct ether_header {
+       uint8_t  ether_dhost[ETH_ALEN];
+       uint8_t  ether_shost[ETH_ALEN];
+       uint16_t ether_type;
+};
+
+#define        ETHERTYPE_PUP           0x0200
+#define ETHERTYPE_SPRITE       0x0500
+#define        ETHERTYPE_IP            0x0800
+#define        ETHERTYPE_ARP           0x0806
+#define        ETHERTYPE_REVARP        0x8035
+#define ETHERTYPE_AT           0x809B
+#define ETHERTYPE_AARP         0x80F3
+#define        ETHERTYPE_VLAN          0x8100
+#define ETHERTYPE_IPX          0x8137
+#define        ETHERTYPE_IPV6          0x86dd
+#define ETHERTYPE_LOOPBACK     0x9000
+
+
+#define        ETHER_ADDR_LEN  ETH_ALEN
+#define        ETHER_TYPE_LEN  2
+#define        ETHER_CRC_LEN   4
+#define        ETHER_HDR_LEN   ETH_HLEN
+#define        ETHER_MIN_LEN   (ETH_ZLEN + ETHER_CRC_LEN)
+#define        ETHER_MAX_LEN   (ETH_FRAME_LEN + ETHER_CRC_LEN)
+
+#define        ETHER_IS_VALID_LEN(foo) \
+       ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+#define        ETHERTYPE_TRAIL         0x1000
+#define        ETHERTYPE_NTRAILER      16
+
+#define        ETHERMTU        ETH_DATA_LEN
+#define        ETHERMIN        (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
+
+#endif
diff --git a/include/net/if.h b/include/net/if.h
new file mode 100644 (file)
index 0000000..2ae5f89
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef _NET_IF_H
+#define _NET_IF_H
+
+#define IF_NAMESIZE 16
+
+struct if_nameindex
+{
+       unsigned int if_index;
+       char *if_name;
+};
+
+unsigned int if_nametoindex (const char *);
+char *if_indextoname (unsigned int, char *);
+struct if_nameindex *if_nameindex (void);
+void if_freenameindex (struct if_nameindex *);
+
+
+
+
+#ifdef _GNU_SOURCE
+
+#include <sys/socket.h>
+
+#define IFF_UP 0x1
+#define IFF_BROADCAST 0x2
+#define IFF_DEBUG 0x4
+#define IFF_LOOPBACK 0x8
+#define IFF_POINTOPOINT 0x10
+#define IFF_NOTRAILERS 0x20
+#define IFF_RUNNING 0x40
+#define IFF_NOARP 0x80
+#define IFF_PROMISC 0x100
+#define IFF_ALLMULTI 0x200
+#define IFF_MASTER 0x400
+#define IFF_SLAVE 0x800
+#define IFF_MULTICAST 0x1000
+#define IFF_PORTSEL 0x2000
+#define IFF_AUTOMEDIA 0x4000
+#define IFF_DYNAMIC 0x8000
+
+struct ifaddr {
+       struct sockaddr ifa_addr;
+       union {
+               struct sockaddr ifu_broadaddr;
+               struct sockaddr ifu_dstaddr;
+       } ifa_ifu;
+       struct iface *ifa_ifp;
+       struct ifaddr *ifa_next;
+};
+
+#define ifa_broadaddr  ifa_ifu.ifu_broadaddr
+#define ifa_dstaddr    ifa_ifu.ifu_dstaddr
+
+struct ifmap {
+       unsigned long int mem_start;
+       unsigned long int mem_end;
+       unsigned short int base_addr;
+       unsigned char irq;
+       unsigned char dma;
+       unsigned char port;
+};
+
+#define IFHWADDRLEN    6
+#define IFNAMSIZ       IF_NAMESIZE
+
+struct ifreq {
+       union {
+               char ifrn_name[IFNAMSIZ];
+       } ifr_ifrn;
+       union {
+               struct sockaddr ifru_addr;
+               struct sockaddr ifru_dstaddr;
+               struct sockaddr ifru_broadaddr;
+               struct sockaddr ifru_netmask;
+               struct sockaddr ifru_hwaddr;
+               short int ifru_flags;
+               int ifru_ivalue;
+               int ifru_mtu;
+               struct ifmap ifru_map;
+               char ifru_slave[IFNAMSIZ];
+               char ifru_newname[IFNAMSIZ];
+               void *ifru_data;
+       } ifr_ifru;
+};
+
+#define ifr_name       ifr_ifrn.ifrn_name
+#define ifr_hwaddr     ifr_ifru.ifru_hwaddr
+#define ifr_addr       ifr_ifru.ifru_addr
+#define ifr_dstaddr    ifr_ifru.ifru_dstaddr
+#define ifr_broadaddr  ifr_ifru.ifru_broadaddr
+#define ifr_netmask    ifr_ifru.ifru_netmask
+#define ifr_flags      ifr_ifru.ifru_flags
+#define ifr_metric     ifr_ifru.ifru_ivalue
+#define ifr_mtu                ifr_ifru.ifru_mtu
+#define ifr_map                ifr_ifru.ifru_map
+#define ifr_slave      ifr_ifru.ifru_slave
+#define ifr_data       ifr_ifru.ifru_data
+#define ifr_ifindex    ifr_ifru.ifru_ivalue
+#define ifr_bandwidth  ifr_ifru.ifru_ivalue
+#define ifr_qlen       ifr_ifru.ifru_ivalue
+#define ifr_newname    ifr_ifru.ifru_newname
+#define _IOT_ifreq     _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
+#define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
+#define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
+
+struct ifconf {
+       int ifc_len;            
+       union {
+               void *ifcu_buf;
+               struct ifreq *ifcu_req;
+       } ifc_ifcu;
+};
+
+#define ifc_buf                ifc_ifcu.ifcu_buf
+#define ifc_req                ifc_ifcu.ifcu_req
+#define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0)
+
+#endif
+
+
+
+#endif
diff --git a/include/net/if_arp.h b/include/net/if_arp.h
new file mode 100644 (file)
index 0000000..bb5eadf
--- /dev/null
@@ -0,0 +1,133 @@
+/* Nonstandard header */
+#ifndef _NET_IF_ARP_H
+#define _NET_IF_ARP_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define MAX_ADDR_LEN   7
+
+#define        ARPOP_REQUEST   1
+#define        ARPOP_REPLY     2
+#define        ARPOP_RREQUEST  3
+#define        ARPOP_RREPLY    4
+#define        ARPOP_InREQUEST 8
+#define        ARPOP_InREPLY   9
+#define        ARPOP_NAK       10
+
+struct arphdr {
+       uint16_t ar_hrd;
+       uint16_t ar_pro;
+       uint8_t ar_hln;
+       uint8_t ar_pln;
+       uint16_t ar_op;
+};
+
+
+#define ARPHRD_NETROM  0
+#define ARPHRD_ETHER   1
+#define        ARPHRD_EETHER   2
+#define        ARPHRD_AX25     3
+#define        ARPHRD_PRONET   4
+#define        ARPHRD_CHAOS    5
+#define        ARPHRD_IEEE802  6
+#define        ARPHRD_ARCNET   7
+#define        ARPHRD_APPLETLK 8
+#define        ARPHRD_DLCI     15
+#define        ARPHRD_ATM      19
+#define        ARPHRD_METRICOM 23
+#define ARPHRD_IEEE1394        24
+#define ARPHRD_EUI64           27
+#define ARPHRD_INFINIBAND      32
+#define ARPHRD_SLIP    256
+#define ARPHRD_CSLIP   257
+#define ARPHRD_SLIP6   258
+#define ARPHRD_CSLIP6  259
+#define ARPHRD_RSRVD   260
+#define ARPHRD_ADAPT   264
+#define ARPHRD_ROSE    270
+#define ARPHRD_X25     271
+#define ARPHRD_HWX25   272
+#define ARPHRD_PPP     512
+#define ARPHRD_CISCO   513
+#define ARPHRD_HDLC    ARPHRD_CISCO
+#define ARPHRD_LAPB    516
+#define ARPHRD_DDCMP   517
+#define        ARPHRD_RAWHDLC  518
+
+#define ARPHRD_TUNNEL  768
+#define ARPHRD_TUNNEL6 769
+#define ARPHRD_FRAD    770
+#define ARPHRD_SKIP    771
+#define ARPHRD_LOOPBACK        772
+#define ARPHRD_LOCALTLK 773
+#define ARPHRD_FDDI    774
+#define ARPHRD_BIF     775
+#define ARPHRD_SIT     776
+#define ARPHRD_IPDDP   777
+#define ARPHRD_IPGRE   778
+#define ARPHRD_PIMREG  779
+#define ARPHRD_HIPPI   780
+#define ARPHRD_ASH     781
+#define ARPHRD_ECONET  782
+#define ARPHRD_IRDA    783
+#define ARPHRD_FCPP    784
+#define ARPHRD_FCAL    785
+#define ARPHRD_FCPL    786
+#define ARPHRD_FCFABRIC 787
+#define ARPHRD_IEEE802_TR 800
+#define ARPHRD_IEEE80211 801
+#define ARPHRD_IEEE80211_PRISM 802
+#define ARPHRD_IEEE80211_RADIOTAP 803
+#define ARPHRD_IEEE802154 804
+#define ARPHRD_IEEE802154_PHY 805
+
+#define ARPHRD_VOID      0xFFFF
+#define ARPHRD_NONE      0xFFFE
+
+struct arpreq {
+       struct sockaddr arp_pa;
+       struct sockaddr arp_ha;
+       int arp_flags;
+       struct sockaddr arp_netmask;
+       char arp_dev[16];
+};
+
+struct arpreq_old {
+       struct sockaddr arp_pa;
+       struct sockaddr arp_ha;
+       int arp_flags;
+       struct sockaddr arp_netmask;
+};
+
+#define ATF_COM                0x02
+#define        ATF_PERM        0x04
+#define        ATF_PUBL        0x08
+#define        ATF_USETRAILERS 0x10
+#define ATF_NETMASK     0x20
+#define ATF_DONTPUB    0x40
+#define ATF_MAGIC      0x80
+
+#define ARPD_UPDATE    0x01
+#define ARPD_LOOKUP    0x02
+#define ARPD_FLUSH     0x03
+
+struct arpd_request {
+       uint16_t req;
+       uint32_t ip;
+       uint32_t dev;
+       uint32_t stamp;
+       uint32_t updated;
+       uint8_t ha[MAX_ADDR_LEN];
+};
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/net/route.h b/include/net/route.h
new file mode 100644 (file)
index 0000000..3aaab97
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef _NET_ROUTE_H
+#define _NET_ROUTE_H
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+
+struct rtentry {
+       unsigned long int rt_pad1;
+       struct sockaddr rt_dst;
+       struct sockaddr rt_gateway;
+       struct sockaddr rt_genmask;
+       unsigned short int rt_flags;
+       short int rt_pad2;
+       unsigned long int rt_pad3;
+       unsigned char rt_tos;
+       unsigned char rt_class;
+       short int rt_pad4[sizeof(long)/2-1];
+       short int rt_metric;
+       char *rt_dev;
+       unsigned long int rt_mtu;
+       unsigned long int rt_window;
+       unsigned short int rt_irtt;
+};
+
+#define rt_mss rt_mtu
+
+
+struct in6_rtmsg {
+       struct in6_addr rtmsg_dst;
+       struct in6_addr rtmsg_src;
+       struct in6_addr rtmsg_gateway;
+       uint32_t rtmsg_type;
+       uint16_t rtmsg_dst_len;
+       uint16_t rtmsg_src_len;
+       uint32_t rtmsg_metric;
+       unsigned long int rtmsg_info;
+       uint32_t rtmsg_flags;
+       int rtmsg_ifindex;
+};
+
+
+#define        RTF_UP          0x0001
+#define        RTF_GATEWAY     0x0002
+
+#define        RTF_HOST        0x0004
+#define RTF_REINSTATE  0x0008
+#define        RTF_DYNAMIC     0x0010
+#define        RTF_MODIFIED    0x0020
+#define RTF_MTU                0x0040
+#define RTF_MSS                RTF_MTU
+#define RTF_WINDOW     0x0080
+#define RTF_IRTT       0x0100
+#define RTF_REJECT     0x0200
+#define        RTF_STATIC      0x0400
+#define        RTF_XRESOLVE    0x0800
+#define RTF_NOFORWARD   0x1000
+#define RTF_THROW      0x2000
+#define RTF_NOPMTUDISC  0x4000
+
+#define RTF_DEFAULT    0x00010000
+#define RTF_ALLONLINK  0x00020000
+#define RTF_ADDRCONF   0x00040000
+
+#define RTF_LINKRT     0x00100000
+#define RTF_NONEXTHOP  0x00200000
+
+#define RTF_CACHE      0x01000000
+#define RTF_FLOW       0x02000000
+#define RTF_POLICY     0x04000000
+
+#define RTCF_VALVE     0x00200000
+#define RTCF_MASQ      0x00400000
+#define RTCF_NAT       0x00800000
+#define RTCF_DOREDIRECT 0x01000000
+#define RTCF_LOG       0x02000000
+#define RTCF_DIRECTSRC 0x04000000
+
+#define RTF_LOCAL      0x80000000
+#define RTF_INTERFACE  0x40000000
+#define RTF_MULTICAST  0x20000000
+#define RTF_BROADCAST  0x10000000
+#define RTF_NAT                0x08000000
+
+#define RTF_ADDRCLASSMASK      0xF8000000
+#define RT_ADDRCLASS(flags)    ((uint32_t) flags >> 23)
+
+#define RT_TOS(tos)            ((tos) & IPTOS_TOS_MASK)
+
+#define RT_LOCALADDR(flags)    ((flags & RTF_ADDRCLASSMASK) \
+                                == (RTF_LOCAL|RTF_INTERFACE))
+
+#define RT_CLASS_UNSPEC                0
+#define RT_CLASS_DEFAULT       253
+
+#define RT_CLASS_MAIN          254
+#define RT_CLASS_LOCAL         255
+#define RT_CLASS_MAX           255
+
+
+#define RTMSG_ACK              NLMSG_ACK
+#define RTMSG_OVERRUN          NLMSG_OVERRUN
+
+#define RTMSG_NEWDEVICE                0x11
+#define RTMSG_DELDEVICE                0x12
+#define RTMSG_NEWROUTE         0x21
+#define RTMSG_DELROUTE         0x22
+#define RTMSG_NEWRULE          0x31
+#define RTMSG_DELRULE          0x32
+#define RTMSG_CONTROL          0x40
+
+#define RTMSG_AR_FAILED                0x51
+
+#endif
diff --git a/include/netdb.h b/include/netdb.h
new file mode 100644 (file)
index 0000000..5f1dd3f
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef        _NETDB_H
+#define        _NETDB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _GNU_SOURCE
+#define __NEED_size_t
+#endif
+
+#define __NEED_socklen_t
+#define __NEED_uint32_t
+
+#include <bits/alltypes.h>
+
+struct addrinfo
+{
+       int ai_flags;
+       int ai_family;
+       int ai_socktype;
+       int ai_protocol;
+       socklen_t ai_addrlen;
+       struct sockaddr *ai_addr;
+       char *ai_canonname;
+       struct addrinfo *ai_next;
+};
+
+#define IPPORT_RESERVED 1024
+
+#define AI_PASSIVE      0x01
+#define AI_CANONNAME    0x02
+#define AI_NUMERICHOST  0x04
+#define AI_V4MAPPED     0x08
+#define AI_ALL          0x10
+#define AI_ADDRCONFIG   0x20
+#define AI_NUMERICSERV  0x400
+
+
+#define NI_NUMERICHOST  0x01
+#define NI_NUMERICSERV  0x02
+#define NI_NOFQDN       0x04
+#define NI_NAMEREQD     0x08
+#define NI_DGRAM        0x10
+/*#define NI_NUMERICSCOPE */
+
+#define NI_MAXHOST 255
+#define NI_MAXSERV 32
+
+#define EAI_BADFLAGS   -1
+#define EAI_NONAME     -2
+#define EAI_AGAIN      -3
+#define EAI_FAIL       -4
+#define EAI_FAMILY     -6
+#define EAI_SOCKTYPE   -7
+#define EAI_SERVICE    -8
+#define EAI_MEMORY     -10
+#define EAI_SYSTEM     -11
+#define EAI_OVERFLOW   -12
+
+int getaddrinfo (const char *, const char *, const struct addrinfo *, struct addrinfo **);
+void freeaddrinfo (struct addrinfo *);
+int getnameinfo (const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);
+const char *gai_strerror(int);
+
+
+/* Legacy functions follow (marked OBsolete in SUS) */
+
+struct netent
+{
+       char *n_name;
+       char **n_aliases;
+       int n_addrtype;
+       uint32_t n_net;
+};
+
+struct hostent
+{
+       char *h_name;
+       char **h_aliases;
+       int h_addrtype;
+       int h_length;
+       char **h_addr_list;
+};
+#define h_addr h_addr_list[0]
+
+struct servent
+{
+       char *s_name;
+       char **s_aliases;
+       int s_port;
+       char *s_proto;
+};
+
+struct protoent
+{
+       char *p_name;
+       char **p_aliases;
+       int p_proto;
+};
+
+extern int h_errno;
+
+#define HOST_NOT_FOUND 1
+#define TRY_AGAIN      2
+#define NO_RECOVERY    3
+#define NO_DATA        4
+
+void sethostent (int);
+void endhostent (void);
+struct hostent *gethostent (void);
+struct hostent *gethostbyaddr (const void *, socklen_t, int);
+struct hostent *gethostbyname (const char *);
+
+void setnetent (int);
+void endnetent (void);
+struct netent *getnetent (void);
+struct netent *getnetbyaddr (uint32_t, int);
+struct netent *getnetbyname (const char *);
+
+void setservent (int);
+void endservent (void);
+struct servent *getservent (void);
+struct servent *getservbyname (const char *, const char *);
+struct servent *getservbyport (int, const char *);
+
+void setprotoent (int);
+void endprotoent (void);
+struct protoent *getprotoent (void);
+struct protoent *getprotobyname (const char *);
+struct protoent *getprotobynumber (int);
+
+#ifdef _GNU_SOURCE
+const char *hstrerror(int);
+int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *);
+int gethostbyname2_r(const char *, int, struct hostent *, char *, size_t, struct hostent **, int *);
+struct hostent *gethostbyname2(const char *, int);
+int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, char *, size_t, struct hostent **, int *);
+int getservbyport_r(int, const char *, struct servent *, char *, size_t, struct servent **);
+int getservbyname_r(const char *, const char *, struct servent *, char *, size_t, struct servent **);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netinet/icmp6.h b/include/netinet/icmp6.h
new file mode 100644 (file)
index 0000000..01269e7
--- /dev/null
@@ -0,0 +1,305 @@
+#ifndef _NETINET_ICMP6_H
+#define _NETINET_ICMP6_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#define ICMP6_FILTER 1
+
+#define ICMP6_FILTER_BLOCK             1
+#define ICMP6_FILTER_PASS              2
+#define ICMP6_FILTER_BLOCKOTHERS       3
+#define ICMP6_FILTER_PASSONLY          4
+
+struct icmp6_filter {
+       uint32_t icmp6_filt[8];
+};
+
+struct icmp6_hdr {
+       uint8_t     icmp6_type;
+       uint8_t     icmp6_code;
+       uint16_t    icmp6_cksum;
+       union {
+               uint32_t  icmp6_un_data32[1];
+               uint16_t  icmp6_un_data16[2];
+               uint8_t   icmp6_un_data8[4];
+       } icmp6_dataun;
+};
+
+#define icmp6_data32    icmp6_dataun.icmp6_un_data32
+#define icmp6_data16    icmp6_dataun.icmp6_un_data16
+#define icmp6_data8     icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr      icmp6_data32[0]
+#define icmp6_mtu       icmp6_data32[0]
+#define icmp6_id        icmp6_data16[0]
+#define icmp6_seq       icmp6_data16[1]
+#define icmp6_maxdelay  icmp6_data16[0]
+
+#define ICMP6_DST_UNREACH             1
+#define ICMP6_PACKET_TOO_BIG          2
+#define ICMP6_TIME_EXCEEDED           3
+#define ICMP6_PARAM_PROB              4
+
+#define ICMP6_INFOMSG_MASK  0x80
+
+#define ICMP6_ECHO_REQUEST          128
+#define ICMP6_ECHO_REPLY            129
+#define MLD_LISTENER_QUERY          130
+#define MLD_LISTENER_REPORT         131
+#define MLD_LISTENER_REDUCTION      132
+
+#define ICMP6_DST_UNREACH_NOROUTE     0
+#define ICMP6_DST_UNREACH_ADMIN       1
+#define ICMP6_DST_UNREACH_BEYONDSCOPE 2
+#define ICMP6_DST_UNREACH_ADDR        3
+#define ICMP6_DST_UNREACH_NOPORT      4
+
+#define ICMP6_TIME_EXCEED_TRANSIT     0
+#define ICMP6_TIME_EXCEED_REASSEMBLY  1
+
+#define ICMP6_PARAMPROB_HEADER        0
+#define ICMP6_PARAMPROB_NEXTHEADER    1
+#define ICMP6_PARAMPROB_OPTION        2
+
+#define ICMP6_FILTER_WILLPASS(type, filterp) \
+       ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+
+#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
+       ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+
+#define ICMP6_FILTER_SETPASS(type, filterp) \
+       ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
+
+#define ICMP6_FILTER_SETBLOCK(type, filterp) \
+       ((((filterp)->icmp6_filt[(type) >> 5]) |=  (1 << ((type) & 31))))
+
+#define ICMP6_FILTER_SETPASSALL(filterp) \
+       memset (filterp, 0, sizeof (struct icmp6_filter));
+
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+       memset (filterp, 0xFF, sizeof (struct icmp6_filter));
+
+#define ND_ROUTER_SOLICIT           133
+#define ND_ROUTER_ADVERT            134
+#define ND_NEIGHBOR_SOLICIT         135
+#define ND_NEIGHBOR_ADVERT          136
+#define ND_REDIRECT                 137
+
+struct nd_router_solicit {
+       struct icmp6_hdr  nd_rs_hdr;
+};
+
+#define nd_rs_type               nd_rs_hdr.icmp6_type
+#define nd_rs_code               nd_rs_hdr.icmp6_code
+#define nd_rs_cksum              nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved           nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert {
+       struct icmp6_hdr  nd_ra_hdr;
+       uint32_t   nd_ra_reachable;
+       uint32_t   nd_ra_retransmit;
+};
+
+#define nd_ra_type               nd_ra_hdr.icmp6_type
+#define nd_ra_code               nd_ra_hdr.icmp6_code
+#define nd_ra_cksum              nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit        nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved     nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED       0x80
+#define ND_RA_FLAG_OTHER         0x40
+#define ND_RA_FLAG_HOME_AGENT    0x20
+#define nd_ra_router_lifetime    nd_ra_hdr.icmp6_data16[1]
+
+struct nd_neighbor_solicit {
+       struct icmp6_hdr  nd_ns_hdr;
+       struct in6_addr   nd_ns_target;
+};
+
+#define nd_ns_type               nd_ns_hdr.icmp6_type
+#define nd_ns_code               nd_ns_hdr.icmp6_code
+#define nd_ns_cksum              nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved           nd_ns_hdr.icmp6_data32[0]
+
+struct nd_neighbor_advert {
+       struct icmp6_hdr  nd_na_hdr;
+       struct in6_addr   nd_na_target;
+};
+
+#define nd_na_type               nd_na_hdr.icmp6_type
+#define nd_na_code               nd_na_hdr.icmp6_code
+#define nd_na_cksum              nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved     nd_na_hdr.icmp6_data32[0]
+#if     __BYTE_ORDER == __BIG_ENDIAN
+#define ND_NA_FLAG_ROUTER        0x80000000
+#define ND_NA_FLAG_SOLICITED     0x40000000
+#define ND_NA_FLAG_OVERRIDE      0x20000000
+#else
+#define ND_NA_FLAG_ROUTER        0x00000080
+#define ND_NA_FLAG_SOLICITED     0x00000040
+#define ND_NA_FLAG_OVERRIDE      0x00000020
+#endif
+
+struct nd_redirect {
+       struct icmp6_hdr  nd_rd_hdr;
+       struct in6_addr   nd_rd_target;
+       struct in6_addr   nd_rd_dst;
+};
+
+#define nd_rd_type               nd_rd_hdr.icmp6_type
+#define nd_rd_code               nd_rd_hdr.icmp6_code
+#define nd_rd_cksum              nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved           nd_rd_hdr.icmp6_data32[0]
+
+struct nd_opt_hdr {
+       uint8_t  nd_opt_type;
+       uint8_t  nd_opt_len;
+};
+
+#define ND_OPT_SOURCE_LINKADDR         1
+#define ND_OPT_TARGET_LINKADDR         2
+#define ND_OPT_PREFIX_INFORMATION      3
+#define ND_OPT_REDIRECTED_HEADER       4
+#define ND_OPT_MTU                     5
+#define ND_OPT_RTR_ADV_INTERVAL                7
+#define ND_OPT_HOME_AGENT_INFO         8
+
+struct nd_opt_prefix_info {
+       uint8_t   nd_opt_pi_type;
+       uint8_t   nd_opt_pi_len;
+       uint8_t   nd_opt_pi_prefix_len;
+       uint8_t   nd_opt_pi_flags_reserved;
+       uint32_t  nd_opt_pi_valid_time;
+       uint32_t  nd_opt_pi_preferred_time;
+       uint32_t  nd_opt_pi_reserved2;
+       struct in6_addr  nd_opt_pi_prefix;
+};
+
+#define ND_OPT_PI_FLAG_ONLINK  0x80
+#define ND_OPT_PI_FLAG_AUTO    0x40
+#define ND_OPT_PI_FLAG_RADDR   0x20
+
+struct nd_opt_rd_hdr {
+       uint8_t   nd_opt_rh_type;
+       uint8_t   nd_opt_rh_len;
+       uint16_t  nd_opt_rh_reserved1;
+       uint32_t  nd_opt_rh_reserved2;
+};
+
+struct nd_opt_mtu {
+       uint8_t   nd_opt_mtu_type;
+       uint8_t   nd_opt_mtu_len;
+       uint16_t  nd_opt_mtu_reserved;
+       uint32_t  nd_opt_mtu_mtu;
+};
+
+struct mld_hdr {
+       struct icmp6_hdr    mld_icmp6_hdr;
+       struct in6_addr     mld_addr;
+};
+
+#define mld_type        mld_icmp6_hdr.icmp6_type
+#define mld_code        mld_icmp6_hdr.icmp6_code
+#define mld_cksum       mld_icmp6_hdr.icmp6_cksum
+#define mld_maxdelay    mld_icmp6_hdr.icmp6_data16[0]
+#define mld_reserved    mld_icmp6_hdr.icmp6_data16[1]
+
+#define ICMP6_ROUTER_RENUMBERING    138
+
+struct icmp6_router_renum {
+       struct icmp6_hdr    rr_hdr;
+       uint8_t             rr_segnum;
+       uint8_t             rr_flags;
+       uint16_t            rr_maxdelay;
+       uint32_t            rr_reserved;
+};
+
+#define rr_type                rr_hdr.icmp6_type
+#define rr_code         rr_hdr.icmp6_code
+#define rr_cksum        rr_hdr.icmp6_cksum
+#define rr_seqnum       rr_hdr.icmp6_data32[0]
+
+#define ICMP6_RR_FLAGS_TEST             0x80
+#define ICMP6_RR_FLAGS_REQRESULT        0x40
+#define ICMP6_RR_FLAGS_FORCEAPPLY       0x20
+#define ICMP6_RR_FLAGS_SPECSITE         0x10
+#define ICMP6_RR_FLAGS_PREVDONE         0x08
+
+struct rr_pco_match {
+       uint8_t             rpm_code;
+       uint8_t             rpm_len;
+       uint8_t             rpm_ordinal;
+       uint8_t             rpm_matchlen;
+       uint8_t             rpm_minlen;
+       uint8_t             rpm_maxlen;
+       uint16_t            rpm_reserved;
+       struct in6_addr     rpm_prefix;
+};
+
+#define RPM_PCO_ADD             1
+#define RPM_PCO_CHANGE          2
+#define RPM_PCO_SETGLOBAL       3
+
+struct rr_pco_use {
+       uint8_t             rpu_uselen;
+       uint8_t             rpu_keeplen;
+       uint8_t             rpu_ramask;
+       uint8_t             rpu_raflags;
+       uint32_t            rpu_vltime;
+       uint32_t            rpu_pltime;
+       uint32_t            rpu_flags;
+       struct in6_addr     rpu_prefix;
+};
+
+#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK  0x20
+#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO    0x10
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
+#else
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40
+#endif
+
+struct rr_result {
+       uint16_t            rrr_flags;
+       uint8_t             rrr_ordinal;
+       uint8_t             rrr_matchedlen;
+       uint32_t            rrr_ifid;
+       struct in6_addr     rrr_prefix;
+};
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB       0x0002
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
+#else
+#define ICMP6_RR_RESULT_FLAGS_OOB       0x0200
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100
+#endif
+
+struct nd_opt_adv_interval {
+       uint8_t   nd_opt_adv_interval_type;
+       uint8_t   nd_opt_adv_interval_len;
+       uint16_t  nd_opt_adv_interval_reserved;
+       uint32_t  nd_opt_adv_interval_ival;
+};
+
+struct nd_opt_home_agent_info {
+       uint8_t   nd_opt_home_agent_info_type;
+       uint8_t   nd_opt_home_agent_info_len;
+       uint16_t  nd_opt_home_agent_info_reserved;
+       uint16_t  nd_opt_home_agent_info_preference;
+       uint16_t  nd_opt_home_agent_info_lifetime;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netinet/if_ether.h b/include/netinet/if_ether.h
new file mode 100644 (file)
index 0000000..65a838a
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef _NETINET_IF_ETHER_H
+#define _NETINET_IF_ETHER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#define ETH_ALEN       6
+#define ETH_HLEN       14
+#define ETH_ZLEN       60
+#define ETH_DATA_LEN   1500
+#define ETH_FRAME_LEN  1514
+#define ETH_FCS_LEN    4
+
+#define ETH_P_LOOP     0x0060
+#define ETH_P_PUP      0x0200
+#define ETH_P_PUPAT    0x0201
+#define ETH_P_IP       0x0800
+#define ETH_P_X25      0x0805
+#define ETH_P_ARP      0x0806
+#define        ETH_P_BPQ       0x08FF
+#define ETH_P_IEEEPUP  0x0a00
+#define ETH_P_IEEEPUPAT        0x0a01
+#define ETH_P_DEC       0x6000
+#define ETH_P_DNA_DL    0x6001
+#define ETH_P_DNA_RC    0x6002
+#define ETH_P_DNA_RT    0x6003
+#define ETH_P_LAT       0x6004
+#define ETH_P_DIAG      0x6005
+#define ETH_P_CUST      0x6006
+#define ETH_P_SCA       0x6007
+#define ETH_P_TEB      0x6558
+#define ETH_P_RARP      0x8035
+#define ETH_P_ATALK    0x809B
+#define ETH_P_AARP     0x80F3
+#define ETH_P_8021Q    0x8100
+#define ETH_P_IPX      0x8137
+#define ETH_P_IPV6     0x86DD
+#define ETH_P_PAUSE    0x8808
+#define ETH_P_SLOW     0x8809
+#define ETH_P_WCCP     0x883E
+#define ETH_P_PPP_DISC 0x8863
+#define ETH_P_PPP_SES  0x8864
+#define ETH_P_MPLS_UC  0x8847
+#define ETH_P_MPLS_MC  0x8848
+#define ETH_P_ATMMPOA  0x884c
+#define ETH_P_ATMFATE  0x8884
+#define ETH_P_PAE      0x888E
+#define ETH_P_AOE      0x88A2
+#define ETH_P_TIPC     0x88CA
+#define ETH_P_FCOE     0x8906
+#define ETH_P_EDSA     0xDADA
+
+#define ETH_P_802_3    0x0001
+#define ETH_P_AX25     0x0002
+#define ETH_P_ALL      0x0003
+#define ETH_P_802_2    0x0004
+#define ETH_P_SNAP     0x0005
+#define ETH_P_DDCMP     0x0006
+#define ETH_P_WAN_PPP   0x0007
+#define ETH_P_PPP_MP    0x0008
+#define ETH_P_LOCALTALK 0x0009
+#define ETH_P_CAN      0x000C
+#define ETH_P_PPPTALK  0x0010
+#define ETH_P_TR_802_2 0x0011
+#define ETH_P_MOBITEX  0x0015
+#define ETH_P_CONTROL  0x0016
+#define ETH_P_IRDA     0x0017
+#define ETH_P_ECONET   0x0018
+#define ETH_P_HDLC     0x0019
+#define ETH_P_ARCNET   0x001A
+#define ETH_P_DSA      0x001B
+#define ETH_P_TRAILER  0x001C
+#define ETH_P_PHONET   0x00F5
+
+struct ethhdr {
+       uint8_t h_dest[ETH_ALEN];
+       uint8_t h_source[ETH_ALEN];
+       uint16_t h_proto;
+};
+
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+
+struct ether_arp {
+       struct  arphdr ea_hdr;
+       uint8_t arp_sha[ETH_ALEN];
+       uint8_t arp_spa[4];
+       uint8_t arp_tha[ETH_ALEN];
+       uint8_t arp_tpa[4];
+};
+#define        arp_hrd ea_hdr.ar_hrd
+#define        arp_pro ea_hdr.ar_pro
+#define        arp_hln ea_hdr.ar_hln
+#define        arp_pln ea_hdr.ar_pln
+#define        arp_op  ea_hdr.ar_op
+
+#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
+do { \
+       (enaddr)[0] = 0x01; \
+       (enaddr)[1] = 0x00; \
+       (enaddr)[2] = 0x5e; \
+       (enaddr)[3] = ((uint8_t *)ipaddr)[1] & 0x7f; \
+       (enaddr)[4] = ((uint8_t *)ipaddr)[2]; \
+       (enaddr)[5] = ((uint8_t *)ipaddr)[3]; \
+} while(0)
+
+
+#endif
diff --git a/include/netinet/in.h b/include/netinet/in.h
new file mode 100644 (file)
index 0000000..a641f6a
--- /dev/null
@@ -0,0 +1,158 @@
+#ifndef        _NETINET_IN_H
+#define        _NETINET_IN_H
+
+#define __NEED_in_addr_t
+#define __NEED_in_port_t
+#define __NEED_sa_family_t
+#define __NEED_struct_in_addr
+#define __NEED_uint8_t
+#define __NEED_uint16_t
+#define __NEED_uint32_t
+
+#include <bits/alltypes.h>
+
+struct sockaddr_in
+{
+       sa_family_t sin_family;
+       in_port_t sin_port;
+       struct in_addr sin_addr;
+       uint8_t sin_zero[8];
+};
+
+struct in6_addr
+{
+       union {
+               uint8_t __s6_addr[16];
+               uint32_t __s6_addr32[4];
+       } __in6_union;
+};
+#define s6_addr __in6_union.__s6_addr
+#define s6_addr32 __in6_union.__s6_addr32
+
+struct sockaddr_in6
+{
+       sa_family_t     sin6_family;
+       in_port_t       sin6_port;
+       uint32_t        sin6_flowinfo;
+       struct in6_addr sin6_addr;
+       uint32_t        sin6_scope_id;
+};
+
+struct ipv6_mreq
+{
+       struct in6_addr ipv6mr_multiaddr;
+       unsigned        ipv6mr_interface;
+};
+
+#define INADDR_ANY        ((in_addr_t) 0x00000000)
+#define INADDR_BROADCAST  ((in_addr_t) 0xffffffff)
+#define INADDR_NONE       ((in_addr_t) 0xffffffff)
+#define INADDR_LOOPBACK   ((in_addr_t) 0x7f000001)
+
+#define IN6ADDR_ANY_INIT      { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
+
+extern const struct in6_addr in6addr_any, in6addr_loopback;
+
+#undef INET_ADDRSTRLEN
+#undef INET6_ADDRSTRLEN
+#define INET_ADDRSTRLEN  16
+#define INET6_ADDRSTRLEN 46
+
+uint32_t htonl(uint32_t);
+uint16_t htons(uint16_t);
+uint32_t ntohl(uint32_t);
+uint16_t ntohs(uint16_t);
+
+#define IPPROTO_IP       0
+#define IPPROTO_ICMP     1
+#define IPPROTO_IGMP     2
+#define IPPROTO_IPIP     4
+#define IPPROTO_TCP      6
+#define IPPROTO_EGP      8
+#define IPPROTO_PUP      12
+#define IPPROTO_UDP      17
+#define IPPROTO_IDP      22
+#define IPPROTO_TP       29
+#define IPPROTO_IPV6     41
+#define IPPROTO_ROUTING  43
+#define IPPROTO_FRAGMENT 44
+#define IPPROTO_RSVP     46
+#define IPPROTO_GRE      47
+#define IPPROTO_ESP      50
+#define IPPROTO_AH       51
+#define IPPROTO_ICMPV6   58
+#define IPPROTO_NONE     59
+#define IPPROTO_DSTOPTS  60
+#define IPPROTO_MTP      92
+#define IPPROTO_ENCAP    98
+#define IPPROTO_PIM      103
+#define IPPROTO_COMP     108
+#define IPPROTO_RAW      255
+
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+        (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
+         ((uint32_t *) (a))[2] == 0 && ((uint32_t *) (a))[3] == 0)
+
+#define IN6_IS_ADDR_LOOPBACK(a) \
+        (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
+         ((uint32_t *) (a))[2] == 0 && \
+         ((uint8_t *) (a))[12] == 0 && ((uint8_t *) (a))[13] == 0 && \
+         ((uint8_t *) (a))[14] == 0 && ((uint8_t *) (a))[15] == 1 )
+
+#define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff)
+
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+        ((((uint8_t *) (a))[0]) == 0xfe && (((uint8_t *) (a))[1] & 0xc0) == 0x80)
+
+#define IN6_IS_ADDR_SITELOCAL(a) \
+        ((((uint8_t *) (a))[0]) == 0xfe && (((uint8_t *) (a))[1] & 0xc0) == 0xc0)
+
+#define IN6_IS_ADDR_V4MAPPED(a) \
+        (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
+         ((uint8_t *) (a))[8] == 0 && ((uint8_t *) (a))[9] == 0 && \
+         ((uint8_t *) (a))[10] == 0xff && ((uint8_t *) (a))[11] == 0xff)
+
+#define IN6_IS_ADDR_V4COMPAT(a) \
+        (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
+         ((uint32_t *) (a))[2] == 0 && ((uint8_t *) (a))[15] > 1)
+
+#define IN6_IS_ADDR_MC_NODELOCAL(a) \
+        (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x1))
+
+#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
+        (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x2))
+
+#define IN6_IS_ADDR_MC_SITELOCAL(a) \
+        (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x5))
+
+#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
+        (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x8))
+
+#define IN6_IS_ADDR_MC_GLOBAL(a) \
+        (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0xe))
+
+#include <bits/in.h>
+
+#if 1 /* FIXME: namespace violation */
+#define        IN_CLASSA(a)            ((((in_addr_t)(a)) & 0x80000000) == 0)
+#define        IN_CLASSA_NET           0xff000000
+#define        IN_CLASSA_NSHIFT        24
+#define        IN_CLASSA_HOST          (0xffffffff & ~IN_CLASSA_NET)
+#define        IN_CLASSA_MAX           128
+#define        IN_CLASSB(a)            ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000)
+#define        IN_CLASSB_NET           0xffff0000
+#define        IN_CLASSB_NSHIFT        16
+#define        IN_CLASSB_HOST          (0xffffffff & ~IN_CLASSB_NET)
+#define        IN_CLASSB_MAX           65536
+#define        IN_CLASSC(a)            ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000)
+#define        IN_CLASSC_NET           0xffffff00
+#define        IN_CLASSC_NSHIFT        8
+#define        IN_CLASSC_HOST          (0xffffffff & ~IN_CLASSC_NET)
+#define        IN_CLASSD(a)            ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000)
+#define        IN_MULTICAST(a)         IN_CLASSD(a)
+#define        IN_EXPERIMENTAL(a)      ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000)
+#define        IN_BADCLASS(a)          ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000)
+#endif
+
+#endif
diff --git a/include/netinet/ip.h b/include/netinet/ip.h
new file mode 100644 (file)
index 0000000..4118741
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef _NETINET_IP_H
+#define _NETINET_IP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <endian.h>
+
+struct timestamp {
+       uint8_t len;
+       uint8_t ptr;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       unsigned int flags:4;
+       unsigned int overflow:4;
+#else
+       unsigned int overflow:4;
+       unsigned int flags:4;
+#endif
+       uint32_t data[9];
+  };
+
+struct iphdr {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       unsigned int ihl:4;
+       unsigned int version:4;
+#else
+       unsigned int version:4;
+       unsigned int ihl:4;
+#endif
+       uint8_t tos;
+       uint16_t tot_len;
+       uint16_t id;
+       uint16_t frag_off;
+       uint8_t ttl;
+       uint8_t protocol;
+       uint16_t check;
+       uint32_t saddr;
+       uint32_t daddr;
+};
+
+struct ip {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       unsigned int ip_hl:4;
+       unsigned int ip_v:4;
+#else
+       unsigned int ip_v:4;
+       unsigned int ip_hl:4;
+#endif
+       uint8_t ip_tos;
+       uint16_t ip_len;
+       uint16_t ip_id;
+       uint16_t ip_off;
+       uint8_t ip_ttl;
+       uint8_t ip_p;
+       uint16_t ip_sum;
+       struct in_addr ip_src, ip_dst;
+};
+
+#define        IP_RF 0x8000
+#define        IP_DF 0x4000
+#define        IP_MF 0x2000
+#define        IP_OFFMASK 0x1fff
+
+struct ip_timestamp {
+       uint8_t ipt_code;
+       uint8_t ipt_len;
+       uint8_t ipt_ptr;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       unsigned int ipt_flg:4;
+       unsigned int ipt_oflw:4;
+#else
+       unsigned int ipt_oflw:4;
+       unsigned int ipt_flg:4;
+#endif
+       uint32_t data[9];
+};
+
+#define        IPVERSION       4
+#define        IP_MAXPACKET    65535
+
+#define        IPTOS_ECN_MASK          0x03
+#define        IPTOS_ECN(x)            ((x) & IPTOS_ECN_MASK)
+#define        IPTOS_ECN_NOT_ECT       0x00
+#define        IPTOS_ECN_ECT1          0x01
+#define        IPTOS_ECN_ECT0          0x02
+#define        IPTOS_ECN_CE            0x03
+
+#define        IPTOS_DSCP_MASK         0xfc
+#define        IPTOS_DSCP(x)           ((x) & IPTOS_DSCP_MASK)
+#define        IPTOS_DSCP_AF11         0x28
+#define        IPTOS_DSCP_AF12         0x30
+#define        IPTOS_DSCP_AF13         0x38
+#define        IPTOS_DSCP_AF21         0x48
+#define        IPTOS_DSCP_AF22         0x50
+#define        IPTOS_DSCP_AF23         0x58
+#define        IPTOS_DSCP_AF31         0x68
+#define        IPTOS_DSCP_AF32         0x70
+#define        IPTOS_DSCP_AF33         0x78
+#define        IPTOS_DSCP_AF41         0x88
+#define        IPTOS_DSCP_AF42         0x90
+#define        IPTOS_DSCP_AF43         0x98
+#define        IPTOS_DSCP_EF           0xb8
+
+#define        IPTOS_TOS_MASK          0x1E
+#define        IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK)
+#define        IPTOS_LOWDELAY          0x10
+#define        IPTOS_THROUGHPUT        0x08
+#define        IPTOS_RELIABILITY       0x04
+#define        IPTOS_LOWCOST           0x02
+#define        IPTOS_MINCOST           IPTOS_LOWCOST
+
+#define        IPTOS_PREC_MASK                 0xe0
+#define        IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK)
+#define        IPTOS_PREC_NETCONTROL           0xe0
+#define        IPTOS_PREC_INTERNETCONTROL      0xc0
+#define        IPTOS_PREC_CRITIC_ECP           0xa0
+#define        IPTOS_PREC_FLASHOVERRIDE        0x80
+#define        IPTOS_PREC_FLASH                0x60
+#define        IPTOS_PREC_IMMEDIATE            0x40
+#define        IPTOS_PREC_PRIORITY             0x20
+#define        IPTOS_PREC_ROUTINE              0x00
+
+#define        IPOPT_COPY              0x80
+#define        IPOPT_CLASS_MASK        0x60
+#define        IPOPT_NUMBER_MASK       0x1f
+
+#define        IPOPT_COPIED(o)         ((o) & IPOPT_COPY)
+#define        IPOPT_CLASS(o)          ((o) & IPOPT_CLASS_MASK)
+#define        IPOPT_NUMBER(o)         ((o) & IPOPT_NUMBER_MASK)
+
+#define        IPOPT_CONTROL           0x00
+#define        IPOPT_RESERVED1         0x20
+#define        IPOPT_DEBMEAS           0x40
+#define        IPOPT_MEASUREMENT       IPOPT_DEBMEAS
+#define        IPOPT_RESERVED2         0x60
+
+#define        IPOPT_EOL               0
+#define        IPOPT_END               IPOPT_EOL
+#define        IPOPT_NOP               1
+#define        IPOPT_NOOP              IPOPT_NOP
+
+#define        IPOPT_RR                7
+#define        IPOPT_TS                68
+#define        IPOPT_TIMESTAMP         IPOPT_TS
+#define        IPOPT_SECURITY          130
+#define        IPOPT_SEC               IPOPT_SECURITY
+#define        IPOPT_LSRR              131
+#define        IPOPT_SATID             136
+#define        IPOPT_SID               IPOPT_SATID
+#define        IPOPT_SSRR              137
+#define        IPOPT_RA                148
+
+#define        IPOPT_OPTVAL            0
+#define        IPOPT_OLEN              1
+#define        IPOPT_OFFSET            2
+#define        IPOPT_MINOFF            4
+
+#define        MAX_IPOPTLEN            40
+
+#define        IPOPT_TS_TSONLY         0
+#define        IPOPT_TS_TSANDADDR      1
+#define        IPOPT_TS_PRESPEC        3
+
+#define        IPOPT_SECUR_UNCLASS     0x0000
+#define        IPOPT_SECUR_CONFID      0xf135
+#define        IPOPT_SECUR_EFTO        0x789a
+#define        IPOPT_SECUR_MMMM        0xbc4d
+#define        IPOPT_SECUR_RESTR       0xaf13
+#define        IPOPT_SECUR_SECRET      0xd788
+#define        IPOPT_SECUR_TOPSECRET   0x6bc5
+
+#define        MAXTTL          255
+#define        IPDEFTTL        64
+#define        IPFRAGTTL       60
+#define        IPTTLDEC        1
+
+#define        IP_MSS          576
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netinet/ip6.h b/include/netinet/ip6.h
new file mode 100644 (file)
index 0000000..a4347a5
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef _NETINET_IP6_H
+#define _NETINET_IP6_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <endian.h>
+
+struct ip6_hdr {
+       union {
+               struct ip6_hdrctl {
+                       uint32_t ip6_un1_flow;
+                       uint16_t ip6_un1_plen;
+                       uint8_t  ip6_un1_nxt;
+                       uint8_t  ip6_un1_hlim;
+               } ip6_un1;
+               uint8_t ip6_un2_vfc;
+       } ip6_ctlun;
+       struct in6_addr ip6_src;
+       struct in6_addr ip6_dst;
+};
+
+#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
+#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+struct ip6_ext {
+       uint8_t  ip6e_nxt;
+       uint8_t  ip6e_len;
+};
+
+struct ip6_hbh {
+       uint8_t  ip6h_nxt;
+       uint8_t  ip6h_len;
+};
+
+struct ip6_dest {
+       uint8_t  ip6d_nxt;
+       uint8_t  ip6d_len;
+};
+
+struct ip6_rthdr {
+       uint8_t  ip6r_nxt;
+       uint8_t  ip6r_len;
+       uint8_t  ip6r_type;
+       uint8_t  ip6r_segleft;
+};
+
+struct ip6_rthdr0 {
+       uint8_t  ip6r0_nxt;
+       uint8_t  ip6r0_len;
+       uint8_t  ip6r0_type;
+       uint8_t  ip6r0_segleft;
+       uint8_t  ip6r0_reserved;
+       uint8_t  ip6r0_slmap[3];
+       struct in6_addr ip6r0_addr[];
+};
+
+struct ip6_frag {
+       uint8_t   ip6f_nxt;
+       uint8_t   ip6f_reserved;
+       uint16_t  ip6f_offlg;
+       uint32_t  ip6f_ident;
+};
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define IP6F_OFF_MASK       0xfff8
+#define IP6F_RESERVED_MASK  0x0006
+#define IP6F_MORE_FRAG      0x0001
+#else
+#define IP6F_OFF_MASK       0xf8ff
+#define IP6F_RESERVED_MASK  0x0600
+#define IP6F_MORE_FRAG      0x0100
+#endif
+
+struct ip6_opt {
+       uint8_t  ip6o_type;
+       uint8_t  ip6o_len;
+};
+
+#define IP6OPT_TYPE(o)         ((o) & 0xc0)
+#define IP6OPT_TYPE_SKIP       0x00
+#define IP6OPT_TYPE_DISCARD    0x40
+#define IP6OPT_TYPE_FORCEICMP  0x80
+#define IP6OPT_TYPE_ICMP       0xc0
+#define IP6OPT_TYPE_MUTABLE    0x20
+
+#define IP6OPT_PAD1    0
+#define IP6OPT_PADN    1
+
+#define IP6OPT_JUMBO           0xc2
+#define IP6OPT_NSAP_ADDR       0xc3
+#define IP6OPT_TUNNEL_LIMIT    0x04
+#define IP6OPT_ROUTER_ALERT    0x05
+
+struct ip6_opt_jumbo {
+       uint8_t  ip6oj_type;
+       uint8_t  ip6oj_len;
+       uint8_t  ip6oj_jumbo_len[4];
+};
+#define IP6OPT_JUMBO_LEN       6
+
+struct ip6_opt_nsap {
+       uint8_t  ip6on_type;
+       uint8_t  ip6on_len;
+       uint8_t  ip6on_src_nsap_len;
+       uint8_t  ip6on_dst_nsap_len;
+};
+
+struct ip6_opt_tunnel {
+       uint8_t  ip6ot_type;
+       uint8_t  ip6ot_len;
+       uint8_t  ip6ot_encap_limit;
+};
+
+struct ip6_opt_router {
+       uint8_t  ip6or_type;
+       uint8_t  ip6or_len;
+       uint8_t  ip6or_value[2];
+};
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define IP6_ALERT_MLD  0x0000
+#define IP6_ALERT_RSVP 0x0001
+#define IP6_ALERT_AN   0x0002
+#else
+#define IP6_ALERT_MLD  0x0000
+#define IP6_ALERT_RSVP 0x0100
+#define IP6_ALERT_AN   0x0200
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netinet/ip_icmp.h b/include/netinet/ip_icmp.h
new file mode 100644 (file)
index 0000000..2f4a86d
--- /dev/null
@@ -0,0 +1,192 @@
+#ifndef _NETINET_IP_ICMP_H
+#define _NETINET_IP_ICMP_H
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct icmphdr {
+       uint8_t type;
+       uint8_t code;
+       uint16_t checksum;
+       union {
+               struct {
+                       uint16_t id;
+                       uint16_t sequence;
+               } echo;
+               uint32_t gateway;
+               struct {
+                       uint16_t __unused;
+                       uint16_t mtu;
+               } frag;
+       } un;
+};
+
+#define ICMP_ECHOREPLY         0
+#define ICMP_DEST_UNREACH      3
+#define ICMP_SOURCE_QUENCH     4
+#define ICMP_REDIRECT          5
+#define ICMP_ECHO              8
+#define ICMP_TIME_EXCEEDED     11
+#define ICMP_PARAMETERPROB     12
+#define ICMP_TIMESTAMP         13
+#define ICMP_TIMESTAMPREPLY    14
+#define ICMP_INFO_REQUEST      15
+#define ICMP_INFO_REPLY                16
+#define ICMP_ADDRESS           17
+#define ICMP_ADDRESSREPLY      18
+#define NR_ICMP_TYPES          18
+
+
+#define ICMP_NET_UNREACH       0
+#define ICMP_HOST_UNREACH      1
+#define ICMP_PROT_UNREACH      2
+#define ICMP_PORT_UNREACH      3
+#define ICMP_FRAG_NEEDED       4
+#define ICMP_SR_FAILED         5
+#define ICMP_NET_UNKNOWN       6
+#define ICMP_HOST_UNKNOWN      7
+#define ICMP_HOST_ISOLATED     8
+#define ICMP_NET_ANO           9
+#define ICMP_HOST_ANO          10
+#define ICMP_NET_UNR_TOS       11
+#define ICMP_HOST_UNR_TOS      12
+#define ICMP_PKT_FILTERED      13
+#define ICMP_PREC_VIOLATION    14
+#define ICMP_PREC_CUTOFF       15
+#define NR_ICMP_UNREACH                15
+
+#define ICMP_REDIR_NET         0
+#define ICMP_REDIR_HOST                1
+#define ICMP_REDIR_NETTOS      2
+#define ICMP_REDIR_HOSTTOS     3
+
+#define ICMP_EXC_TTL           0
+#define ICMP_EXC_FRAGTIME      1
+
+
+struct icmp_ra_addr {
+       uint32_t ira_addr;
+       uint32_t ira_preference;
+};
+
+struct icmp {
+       uint8_t  icmp_type;
+       uint8_t  icmp_code;
+       uint16_t icmp_cksum;
+       union {
+               uint8_t ih_pptr;
+               struct in_addr ih_gwaddr;
+               struct ih_idseq {
+                       uint16_t icd_id;
+                       uint16_t icd_seq;
+               } ih_idseq;
+               uint32_t ih_void;
+
+               struct ih_pmtu {
+                       uint16_t ipm_void;
+                       uint16_t ipm_nextmtu;
+               } ih_pmtu;
+
+               struct ih_rtradv {
+                       uint8_t irt_num_addrs;
+                       uint8_t irt_wpa;
+                       uint16_t irt_lifetime;
+               } ih_rtradv;
+       } icmp_hun;
+       union {
+               struct {
+                       uint32_t its_otime;
+                       uint32_t its_rtime;
+                       uint32_t its_ttime;
+               } id_ts;
+               struct {
+                       struct ip idi_ip;
+               } id_ip;
+               struct icmp_ra_addr id_radv;
+               uint32_t   id_mask;
+               uint8_t    id_data[1];
+       } icmp_dun;
+};
+
+#define        icmp_pptr       icmp_hun.ih_pptr
+#define        icmp_gwaddr     icmp_hun.ih_gwaddr
+#define        icmp_id         icmp_hun.ih_idseq.icd_id
+#define        icmp_seq        icmp_hun.ih_idseq.icd_seq
+#define        icmp_void       icmp_hun.ih_void
+#define        icmp_pmvoid     icmp_hun.ih_pmtu.ipm_void
+#define        icmp_nextmtu    icmp_hun.ih_pmtu.ipm_nextmtu
+#define        icmp_num_addrs  icmp_hun.ih_rtradv.irt_num_addrs
+#define        icmp_wpa        icmp_hun.ih_rtradv.irt_wpa
+#define        icmp_lifetime   icmp_hun.ih_rtradv.irt_lifetime
+#define        icmp_otime      icmp_dun.id_ts.its_otime
+#define        icmp_rtime      icmp_dun.id_ts.its_rtime
+#define        icmp_ttime      icmp_dun.id_ts.its_ttime
+#define        icmp_ip         icmp_dun.id_ip.idi_ip
+#define        icmp_radv       icmp_dun.id_radv
+#define        icmp_mask       icmp_dun.id_mask
+#define        icmp_data       icmp_dun.id_data
+
+#define        ICMP_MINLEN     8
+#define        ICMP_TSLEN      (8 + 3 * sizeof (n_time))
+#define        ICMP_MASKLEN    12
+#define        ICMP_ADVLENMIN  (8 + sizeof (struct ip) + 8)
+#define        ICMP_ADVLEN(p)  (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
+
+#define        ICMP_UNREACH            3
+#define        ICMP_SOURCEQUENCH       4
+#define        ICMP_ROUTERADVERT       9
+#define        ICMP_ROUTERSOLICIT      10
+#define        ICMP_TIMXCEED           11
+#define        ICMP_PARAMPROB          12
+#define        ICMP_TSTAMP             13
+#define        ICMP_TSTAMPREPLY        14
+#define        ICMP_IREQ               15
+#define        ICMP_IREQREPLY          16
+#define        ICMP_MASKREQ            17
+#define        ICMP_MASKREPLY          18
+#define        ICMP_MAXTYPE            18
+
+#define        ICMP_UNREACH_NET                0
+#define        ICMP_UNREACH_HOST               1
+#define        ICMP_UNREACH_PROTOCOL           2
+#define        ICMP_UNREACH_PORT               3
+#define        ICMP_UNREACH_NEEDFRAG           4
+#define        ICMP_UNREACH_SRCFAIL            5
+#define        ICMP_UNREACH_NET_UNKNOWN        6
+#define        ICMP_UNREACH_HOST_UNKNOWN       7
+#define        ICMP_UNREACH_ISOLATED           8
+#define        ICMP_UNREACH_NET_PROHIB         9
+#define        ICMP_UNREACH_HOST_PROHIB        10
+#define        ICMP_UNREACH_TOSNET             11
+#define        ICMP_UNREACH_TOSHOST            12
+#define        ICMP_UNREACH_FILTER_PROHIB      13
+#define        ICMP_UNREACH_HOST_PRECEDENCE    14
+#define        ICMP_UNREACH_PRECEDENCE_CUTOFF  15
+
+#define        ICMP_REDIRECT_NET       0
+#define        ICMP_REDIRECT_HOST      1
+#define        ICMP_REDIRECT_TOSNET    2
+#define        ICMP_REDIRECT_TOSHOST   3
+
+#define        ICMP_TIMXCEED_INTRANS   0
+#define        ICMP_TIMXCEED_REASS     1
+
+#define        ICMP_PARAMPROB_OPTABSENT 1
+
+#define        ICMP_INFOTYPE(type) \
+       ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
+       (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
+       (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
+       (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
+       (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h
new file mode 100644 (file)
index 0000000..ea32ca0
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _NETINET_TCP_H
+#define _NETINET_TCP_H
+
+#include <bits/tcp.h>
+
+#endif
diff --git a/include/netinet/udp.h b/include/netinet/udp.h
new file mode 100644 (file)
index 0000000..15b9145
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _NETINET_UDP_H
+#define _NETINET_UDP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+struct udphdr {
+       uint16_t source;
+       uint16_t dest;
+       uint16_t len;
+       uint16_t check;
+};
+
+#define uh_sport source
+#define uh_dport dest
+#define uh_ulen len
+#define uh_sum check
+
+#define UDP_CORK       1
+#define UDP_ENCAP      100
+
+#define UDP_ENCAP_ESPINUDP_NON_IKE 1
+#define UDP_ENCAP_ESPINUDP     2
+#define UDP_ENCAP_L2TPINUDP    3
+
+#define SOL_UDP            17
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/nl_types.h b/include/nl_types.h
new file mode 100644 (file)
index 0000000..ca61efb
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _NL_TYPES_H
+#define _NL_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NL_SETD 1
+#define NL_CAT_LOCALE 1
+
+#define __NEED_nl_item
+#include <bits/alltypes.h>
+
+typedef long nl_catd;
+
+nl_catd catopen (const char *, int);
+char *catgets (nl_catd, int, int, const char *);
+int catclose (nl_catd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/paths.h b/include/paths.h
new file mode 100644 (file)
index 0000000..8a38ba7
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _PATHS_H_
+#define        _PATHS_H_
+
+#define        _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin"
+#define        _PATH_STDPATH "/bin:/usr/bin:/sbin:/usr/sbin"
+
+#define        _PATH_BSHELL    "/bin/sh"
+#define        _PATH_CONSOLE   "/dev/console"
+#define        _PATH_CSHELL    "/bin/csh"
+#define        _PATH_DEVDB     "/var/run/dev.db"
+#define        _PATH_DEVNULL   "/dev/null"
+#define        _PATH_DRUM      "/dev/drum"
+#define        _PATH_GSHADOW   "/etc/gshadow"
+#define        _PATH_KLOG      "/proc/kmsg"
+#define        _PATH_KMEM      "/dev/kmem"
+#define        _PATH_LASTLOG   "/var/log/lastlog"
+#define        _PATH_MAILDIR   "/var/mail"
+#define        _PATH_MAN       "/usr/share/man"
+#define        _PATH_MEM       "/dev/mem"
+#define        _PATH_MNTTAB    "/etc/fstab"
+#define        _PATH_MOUNTED   "/etc/mtab"
+#define        _PATH_NOLOGIN   "/etc/nologin"
+#define        _PATH_PRESERVE  "/var/lib"
+#define        _PATH_RWHODIR   "/var/spool/rwho"
+#define        _PATH_SENDMAIL  "/usr/sbin/sendmail"
+#define        _PATH_SHADOW    "/etc/shadow"
+#define        _PATH_SHELLS    "/etc/shells"
+#define        _PATH_TTY       "/dev/tty"
+#define        _PATH_UNIX      "/boot/vmlinux"
+#define _PATH_UTMP     "/var/run/utmp"
+#define        _PATH_VI        "/usr/bin/vi"
+#define _PATH_WTMP     "/var/log/wtmp"
+
+#define        _PATH_DEV       "/dev/"
+#define        _PATH_TMP       "/tmp/"
+#define        _PATH_VARDB     "/var/lib/misc/"
+#define        _PATH_VARRUN    "/var/run/"
+#define        _PATH_VARTMP    "/var/tmp/"
+
+#endif
diff --git a/include/poll.h b/include/poll.h
new file mode 100644 (file)
index 0000000..f868ab5
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef        _POLL_H
+#define        _POLL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define POLLIN     0x001
+#define POLLPRI    0x002
+#define POLLOUT    0x004
+#define POLLERR    0x008
+#define POLLHUP    0x010
+#define POLLNVAL   0x020
+#define POLLRDNORM 0x040
+#define POLLRDBAND 0x080
+#define POLLWRNORM 0x100
+#define POLLWRBAND 0x200
+#define POLLMSG    0x400
+
+typedef unsigned int nfds_t;
+
+struct pollfd
+{
+       int fd;
+       short events;
+       short revents;
+};
+
+int poll (struct pollfd *, nfds_t, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/pthread.h b/include/pthread.h
new file mode 100644 (file)
index 0000000..ce6273d
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef _PTHREAD_H
+#define _PTHREAD_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_time_t
+#define __NEED_struct_timespec
+#define __NEED_sigset_t
+#define __NEED_pthread_t
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+struct sched_param;
+
+typedef int pthread_once_t, pthread_key_t, pthread_spinlock_t;
+typedef int pthread_mutexattr_t, pthread_condattr_t, pthread_barrierattr_t;
+
+typedef struct {
+       size_t __guardsize;
+       size_t __stacksize;
+       unsigned __detach : 1;
+       unsigned __pad : 31;
+       int __attr[6];
+} pthread_attr_t;
+
+typedef struct {
+       int __attr[2];
+} pthread_rwlockattr_t;
+
+typedef struct {
+       int __type;
+       int __lock;
+       pthread_t __owner;
+       int __pad2;
+       int __waiters;
+       int __pad;
+} pthread_mutex_t;
+
+typedef struct {
+       int __block;
+       int __pad[11];
+} pthread_cond_t;
+
+typedef struct {
+       int __wrlock;
+       int __readers;
+       int __waiters;
+       int __owner;
+       int __pad[4];
+} pthread_rwlock_t;
+
+typedef struct {
+       int __count;
+       int __limit;
+       int __left;
+       int __waiters;
+       int __barrier[1];
+} pthread_barrier_t;
+
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED 1
+
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_DEFAULT 0
+#define PTHREAD_MUTEX_RECURSIVE 1
+#define PTHREAD_MUTEX_ERRORCHECK 2
+
+#define PTHREAD_MUTEX_STALLED 0
+#define PTHREAD_MUTEX_ROBUST 1
+
+#define PTHREAD_PRIO_NONE 0
+#define PTHREAD_PRIO_INHERIT 1
+#define PTHREAD_PRIO_PROTECT 2
+
+#define PTHREAD_INHERIT_SCHED 0
+#define PTHREAD_EXPLICIT_SCHED 1
+
+#define PTHREAD_SCOPE_SYSTEM 0
+#define PTHREAD_SCOPE_PROCESS 1
+
+#define PTHREAD_PROCESS_PRIVATE 0
+#define PTHREAD_PROCESS_SHARED 1
+
+
+#define PTHREAD_MUTEX_INITIALIZER {0}
+#define PTHREAD_RWLOCK_INITIALIZER {0}
+#define PTHREAD_COND_INITIALIZER {0}
+#define PTHREAD_ONCE_INIT 0
+
+
+#define PTHREAD_CANCEL_ENABLE 0
+#define PTHREAD_CANCEL_DISABLE 1
+
+#define PTHREAD_CANCEL_DEFERRED 0
+#define PTHREAD_CANCEL_ASYNCHRONOUS 1
+
+#define PTHREAD_CANCELLED ((void *)-1)
+
+
+#define PTHREAD_BARRIER_SERIAL_THREAD (-1)
+
+
+int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
+int pthread_detach(pthread_t);
+void pthread_exit(void *);
+int pthread_join(pthread_t, void **);
+
+pthread_t pthread_self(void);
+int pthread_equal(pthread_t, pthread_t);
+
+int pthread_setcancelstate(int, int *);
+int pthread_setcanceltype(int, int *);
+void pthread_testcancel(void);
+int pthread_cancel(pthread_t);
+
+int pthread_once(pthread_once_t *, void (*)(void));
+
+int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
+int pthread_mutex_lock(pthread_mutex_t *);
+int pthread_mutex_unlock(pthread_mutex_t *);
+int pthread_mutex_trylock(pthread_mutex_t *);
+int pthread_mutex_destroy(pthread_mutex_t *);
+
+int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
+int pthread_cond_destroy(pthread_cond_t *);
+int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
+int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
+int pthread_cond_broadcast(pthread_cond_t *);
+int pthread_cond_signal(pthread_cond_t *);
+
+int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
+int pthread_rwlock_destroy(pthread_rwlock_t *);
+int pthread_rwlock_rdlock(pthread_rwlock_t *);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *, const struct timespec *);
+int pthread_rwlock_wrlock(pthread_rwlock_t *);
+int pthread_rwlock_trywrlock(pthread_rwlock_t *);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *, const struct timespec *);
+int pthread_rwlock_unlock(pthread_rwlock_t *);
+
+int pthread_spin_init(pthread_spinlock_t *, int);
+int pthread_spin_destroy(pthread_spinlock_t *);
+int pthread_spin_lock(pthread_spinlock_t *);
+int pthread_spin_trylock(pthread_spinlock_t *);
+int pthread_spin_unlock(pthread_spinlock_t *);
+
+int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *, unsigned);
+int pthread_barrier_destroy(pthread_barrier_t *);
+int pthread_barrier_wait(pthread_barrier_t *);
+
+int pthread_key_create(pthread_key_t *, void (*)(void *));
+int pthread_key_delete(pthread_key_t);
+void *pthread_getspecific(pthread_key_t);
+int pthread_setspecific(pthread_key_t, const void *);
+
+int pthread_attr_init(pthread_attr_t *);
+int pthread_attr_destroy(pthread_attr_t *);
+
+int pthread_attr_getguardsize(pthread_attr_t *, size_t *);
+int pthread_attr_setguardsize(pthread_attr_t *, size_t);
+int pthread_attr_getstacksize(pthread_attr_t *, size_t *);
+int pthread_attr_setstacksize(pthread_attr_t *, size_t);
+int pthread_attr_getdetachstate(pthread_attr_t *, int *);
+int pthread_attr_setdetachstate(pthread_attr_t *, int);
+int pthread_attr_getstack(pthread_attr_t *, void **, size_t *);
+int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
+int pthread_attr_getscope(pthread_attr_t *, int *);
+int pthread_attr_setscope(pthread_attr_t *, int);
+int pthread_attr_getschedpolicy(pthread_attr_t *, int *);
+int pthread_attr_setschedpolicy(pthread_attr_t *, int);
+int pthread_attr_getschedparam(pthread_attr_t *, struct sched_param *);
+int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
+int pthread_attr_getinheritsched(pthread_attr_t *, int *);
+int pthread_attr_setinheritsched(pthread_attr_t *, int);
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *);
+int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
+int pthread_mutexattr_getrobust(const pthread_mutexattr_t *, int *);
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
+int pthread_mutexattr_init(pthread_mutexattr_t *);
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int);
+int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
+
+int pthread_barrierattr_destroy(pthread_barrierattr_t *);
+int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *);
+int pthread_barrierattr_init(pthread_barrierattr_t *);
+int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
+
+#include <bits/pthread.h>
+
+int __setjmp(void *);
+void __pthread_register_cancel(struct __ptcb *);
+void __pthread_unregister_cancel(struct __ptcb *);
+void __pthread_unwind_next(struct __ptcb *);
+
+#define pthread_cleanup_push(f, x) \
+do { struct __ptcb __cb; void (*__f)(void *) = (f); void *__x = (x); \
+if (__setjmp(__cb.__jb)) __f(__x), __pthread_unwind_next(&__cb); \
+__pthread_register_cancel(&__cb); {
+
+#define pthread_cleanup_pop(r) ; } \
+__pthread_unregister_cancel(&__cb); \
+if (r) __f(__x); } while (0)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/pty.h b/include/pty.h
new file mode 100644 (file)
index 0000000..9444e5e
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef        _PTY_H
+#define        _PTY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int openpty(int *, int *, char *, const struct termios *, const struct winsize *);
+
+#ifdef __cplusplus
+extern }
+#endif
+
+#endif
diff --git a/include/pwd.h b/include/pwd.h
new file mode 100644 (file)
index 0000000..5abfbfd
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _PWD_H
+#define _PWD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+#define __NEED_uid_t
+#define __NEED_gid_t
+
+#include <bits/alltypes.h>
+
+struct passwd
+{
+       char *pw_name;
+       char *pw_passwd;
+       uid_t pw_uid;
+       gid_t pw_gid;
+       char *pw_gecos;
+       char *pw_dir;
+       char *pw_shell;
+};
+
+void setpwent (void);
+void endpwent (void);
+struct passwd *getpwent (void);
+
+struct passwd *getpwuid (uid_t);
+struct passwd *getpwnam (const char *);
+int getpwuid_r (uid_t, struct passwd *, char *, size_t, struct passwd **);
+int getpwnam_r (const char *, struct passwd *, char *, size_t, struct passwd **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/regex.h b/include/regex.h
new file mode 100644 (file)
index 0000000..3673bfa
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _REGEX_H
+#define _REGEX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+typedef long regoff_t;
+
+typedef struct {
+       size_t re_nsub;
+       void *__opaque;
+} regex_t;
+
+typedef struct {
+       regoff_t rm_so;
+       regoff_t rm_eo;
+} regmatch_t;
+
+#define REG_EXTENDED    1
+#define REG_ICASE       2
+#define REG_NEWLINE     4
+#define REG_NOSUB       8
+
+#define REG_NOTBOL      1
+#define REG_NOTEOL      2
+
+#define REG_OK          0
+#define REG_NOMATCH     1
+#define REG_BADPAT      2
+#define REG_ECOLLATE    3
+#define REG_ECTYPE      4
+#define REG_EESCAPE     5
+#define REG_ESUBREG     6
+#define REG_EBRACK      7
+#define REG_EPAREN      8
+#define REG_EBRACE      9
+#define REG_BADBR       10
+#define REG_ERANGE      11
+#define REG_ESPACE      12
+#define REG_BADRPT      13
+
+#define REG_ENOSYS      -1
+
+int regcomp(regex_t *, const char *, int);
+int regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
+void regfree(regex_t *);
+
+size_t regerror(int, const regex_t *, char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/resolv.h b/include/resolv.h
new file mode 100644 (file)
index 0000000..3b77fc7
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef _RESOLV_H_
+#define _RESOLV_H_
+
+#include <stdint.h>
+#include <arpa/nameser.h>
+#include <netinet/in.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAXNS                  3
+#define MAXDFLSRCH             3
+#define MAXDNSRCH              6
+#define LOCALDOMAINPARTS       2
+
+#define RES_TIMEOUT            5
+#define MAXRESOLVSORT          10
+#define RES_MAXNDOTS           15
+#define RES_MAXRETRANS         30
+#define RES_MAXRETRY           5
+#define RES_DFLRETRY           2
+#define RES_MAXTIME            65535
+
+/* unused; purely for broken apps */
+typedef struct __res_state {
+       int retrans;
+       int retry;
+       unsigned long options;
+       int nscount;
+       struct sockaddr_in nsaddr_list[MAXNS];
+# define nsaddr        nsaddr_list[0]
+       unsigned short id;
+       char *dnsrch[MAXDNSRCH+1];
+       char defdname[256];
+       unsigned long pfcode;
+       unsigned ndots:4;
+       unsigned nsort:4;
+       unsigned ipv6_unavail:1;
+       unsigned unused:23;
+       struct {
+               struct in_addr addr;
+               uint32_t mask;
+       } sort_list[MAXRESOLVSORT];
+       void *qhook;
+       void *rhook;
+       int res_h_errno;
+       int _vcsock;
+       unsigned _flags;
+       union {
+               char pad[52];
+               struct {
+                       uint16_t                nscount;
+                       uint16_t                nsmap[MAXNS];
+                       int                     nssocks[MAXNS];
+                       uint16_t                nscount6;
+                       uint16_t                nsinit;
+                       struct sockaddr_in6     *nsaddrs[MAXNS];
+                       unsigned int            _initstamp[2];
+               } _ext;
+       } _u;
+} *res_state;
+
+#define        __RES   19991006
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF        "/etc/resolv.conf"
+#endif
+
+struct res_sym {
+       int number;
+       char *name;
+       char *humanname;
+};
+
+#define        RES_F_VC        0x00000001
+#define        RES_F_CONN      0x00000002
+#define RES_F_EDNS0ERR 0x00000004
+
+#define        RES_EXHAUSTIVE  0x00000001
+
+#define RES_INIT       0x00000001
+#define RES_DEBUG      0x00000002
+#define RES_AAONLY     0x00000004
+#define RES_USEVC      0x00000008
+#define RES_PRIMARY    0x00000010
+#define RES_IGNTC      0x00000020
+#define RES_RECURSE    0x00000040
+#define RES_DEFNAMES   0x00000080
+#define RES_STAYOPEN   0x00000100
+#define RES_DNSRCH     0x00000200
+#define        RES_INSECURE1   0x00000400
+#define        RES_INSECURE2   0x00000800
+#define        RES_NOALIASES   0x00001000
+#define        RES_USE_INET6   0x00002000
+#define RES_ROTATE     0x00004000
+#define        RES_NOCHECKNAME 0x00008000
+#define        RES_KEEPTSIG    0x00010000
+#define        RES_BLAST       0x00020000
+#define RES_USEBSTRING 0x00040000
+#define RES_NOIP6DOTINT        0x00080000
+#define RES_USE_EDNS0  0x00100000
+#define RES_SNGLKUP    0x00200000
+#define RES_SNGLKUPREOP        0x00400000
+#define RES_USE_DNSSEC 0x00800000
+
+#define RES_DEFAULT    (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
+
+#define RES_PRF_STATS  0x00000001
+#define RES_PRF_UPDATE 0x00000002
+#define RES_PRF_CLASS   0x00000004
+#define RES_PRF_CMD    0x00000008
+#define RES_PRF_QUES   0x00000010
+#define RES_PRF_ANS    0x00000020
+#define RES_PRF_AUTH   0x00000040
+#define RES_PRF_ADD    0x00000080
+#define RES_PRF_HEAD1  0x00000100
+#define RES_PRF_HEAD2  0x00000200
+#define RES_PRF_TTLID  0x00000400
+#define RES_PRF_HEADX  0x00000800
+#define RES_PRF_QUERY  0x00001000
+#define RES_PRF_REPLY  0x00002000
+#define RES_PRF_INIT   0x00004000
+
+extern struct __res_state *__res_state(void);
+#define _res (*__res_state())
+
+struct rrec;
+
+int res_init(void);
+int res_query(const char *, int, int, unsigned char *, int);
+int res_querydomain(const char *, const char *, int, int, unsigned char *, int);
+int res_search(const char *, int, int, unsigned char *, int);
+int res_mkquery(int, const char *, int, int, char *, int, struct rrec *, char *, int);
+int res_send(const char *, int, char *, int);
+int dn_comp(unsigned char *, unsigned char *, int, unsigned char **, unsigned char *, unsigned char **);
+int dn_expand(unsigned char *, unsigned char *, unsigned char *, unsigned char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sched.h b/include/sched.h
new file mode 100644 (file)
index 0000000..4d8bd3d
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _SCHED_H
+#define _SCHED_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_struct_timespec
+#define __NEED_pid_t
+#define __NEED_time_t
+
+#include <bits/alltypes.h>
+
+struct sched_param {
+       int sched_priority;
+       int sched_ss_low_priority;
+       struct timespec sched_ss_repl_period;
+       struct timespec sched_ss_init_budget;
+       int sched_ss_max_repl;
+};
+
+int    sched_get_priority_max(int);
+int    sched_get_priority_min(int);
+int    sched_getparam(pid_t, struct sched_param *);
+int    sched_getscheduler(pid_t);
+int    sched_rr_get_interval(pid_t, struct timespec *);
+int    sched_setparam(pid_t, const struct sched_param *);
+int    sched_setscheduler(pid_t, int, const struct sched_param *);
+int     sched_yield(void);
+
+#define SCHED_OTHER 0
+#define SCHED_FIFO 1
+#define SCHED_RR 2
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/search.h b/include/search.h
new file mode 100644 (file)
index 0000000..9254ed0
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _SEARCH_H
+#define _SEARCH_H
+
+// FIXME!!!
+
+#endif
diff --git a/include/semaphore.h b/include/semaphore.h
new file mode 100644 (file)
index 0000000..5b68986
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _SEMAPHORE_H
+#define _SEMAPHORE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SEM_FAILED ((sem_t *)0)
+
+typedef struct {
+       long __val[4];
+} sem_t;
+
+int    sem_close(sem_t *);
+int    sem_destroy(sem_t *);
+int    sem_getvalue(sem_t *, int *);
+int    sem_init(sem_t *, int, unsigned);
+sem_t *sem_open(const char *, int, ...);
+int    sem_post(sem_t *);
+int    sem_timedwait(sem_t *, const struct timespec *);
+int    sem_trywait(sem_t *);
+int    sem_unlink(const char *);
+int    sem_wait(sem_t *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/setjmp.h b/include/setjmp.h
new file mode 100644 (file)
index 0000000..6288c84
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef        _SETJMP_H
+#define        _SETJMP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bits/setjmp.h>
+typedef unsigned long sigjmp_buf[(1024+sizeof(jmp_buf))/sizeof(long)];
+
+#ifdef _GNU_SOURCE
+#define jmp_buf sigjmp_buf
+#endif
+
+int setjmp (jmp_buf);
+int _setjmp (jmp_buf);
+int sigsetjmp (sigjmp_buf, int);
+
+void longjmp (jmp_buf, int);
+void _longjmp (jmp_buf, int);
+void siglongjmp (sigjmp_buf, int);
+
+#define setjmp setjmp
+#define longjmp longjmp
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/shadow.h b/include/shadow.h
new file mode 100644 (file)
index 0000000..2b1be41
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _SHADOW_H
+#define _SHADOW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        __NEED_FILE
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+#define        SHADOW "/etc/shadow"
+
+struct spwd {
+       char *sp_namp;
+       char *sp_pwdp;
+       long sp_lstchg;
+       long sp_min;
+       long sp_max;
+       long sp_warn;
+       long sp_inact;
+       long sp_expire;
+       unsigned long sp_flag;
+};
+
+void setspent(void);
+void endspent(void);
+struct spwd *getspent(void);
+struct spwd *fgetspent(FILE *);
+struct spwd *sgetspent(const char *);
+int putspent(const struct spwd *, FILE *);
+
+struct spwd *getspnam(const char *);
+int getspnam_r(const char *, struct spwd *, char *, size_t, struct spwd **);
+
+int lckpwdf(void);
+int ulckpwdf(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/signal.h b/include/signal.h
new file mode 100644 (file)
index 0000000..540236a
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef _SIGNAL_H
+#define _SIGNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+#define __NEED_pid_t
+#define __NEED_uid_t
+#define __NEED_struct_timespec
+#define __NEED_pthread_t
+#define __NEED_time_t
+#define __NEED_clock_t
+#define __NEED_sigset_t
+#define __NEED_siginfo_t
+
+#include <bits/alltypes.h>
+
+typedef int sig_atomic_t;
+
+struct sigaction
+{
+       union {
+               void (*sa_handler)(int);
+               void (*sa_sigaction)(int, siginfo_t *, void *);
+       } __sa_handler;
+       sigset_t sa_mask;
+       int sa_flags;
+       void (*__sa_restorer)(void);    
+};
+#define sa_handler   __sa_handler.sa_handler
+#define sa_sigaction __sa_handler.sa_sigaction
+
+typedef struct
+{
+       void *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+union sigval
+{
+       int sival_int;
+       void *sival_ptr;
+};
+
+#include <bits/signal.h>
+
+int __libc_current_sigrtmin(void);
+int __libc_current_sigrtmax(void);
+
+#define SIGRTMIN  (__libc_current_sigrtmin())
+#define SIGRTMAX  (__libc_current_sigrtmax())
+
+void (*signal(int, void (*)(int)))(int);
+void (*bsd_signal(int, void (*)(int)))(int);
+int kill(pid_t, int);
+int killpg(pid_t, int);
+int raise(int);
+int sigpause(int);
+
+int sigemptyset(sigset_t *);
+int sigfillset(sigset_t *);
+int sigaddset(sigset_t *, int);
+int sigdelset(sigset_t *, int);
+int sigismember(const sigset_t *, int);
+
+int sigprocmask(int, const sigset_t *, sigset_t *);
+int sigsuspend(const sigset_t *);
+int sigaction(int, const struct sigaction *, struct sigaction *);
+int sigpending(sigset_t *);
+int sigwait(const sigset_t *, int *);
+int sigwaitinfo(const sigset_t *, siginfo_t *);
+int sigtimedwait(const sigset_t *, siginfo_t *, const struct timespec *);
+int sigqueue(pid_t, int, const union sigval);
+
+int siginterrupt(int, int);
+
+int sigaltstack(const stack_t *, stack_t *);
+
+int sighold(int);
+int sigrelse(int);
+int sigignore(int);
+void (*sigset(int, void (*)(int)))(int);
+
+int pthread_sigmask(int, const sigset_t *, sigset_t *);
+int pthread_kill(pthread_t, int);
+
+#ifdef _GNU_SOURCE
+typedef int (*sighandler_t)(int);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/stdarg.h b/include/stdarg.h
new file mode 100644 (file)
index 0000000..cb18778
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _STDARG_H
+#define _STDARG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_va_list
+
+#include <bits/alltypes.h>
+
+#define __VA_ALIGNED_SIZE(x) ((sizeof(x) + sizeof(int) - 1) & ~(sizeof(int) - 1))
+
+#define va_start(ap, last) ((ap) = (void *)(((char *)&(last)) + __VA_ALIGNED_SIZE(last)))
+#define va_end(ap) ((void)0)
+#define va_copy(dest, src) ((dest) = (src))
+
+#if 0
+#define va_arg(ap, type) \
+       ( ((ap) = (va_list)((char *)(ap) + sizeof(type))), \
+       *(type *)(void *)((char *)(ap) - sizeof(type)) )
+#endif
+
+#define va_arg(ap, type) \
+       ( ((ap) = (va_list)((char *)(ap) + __VA_ALIGNED_SIZE(type))), \
+       *(type *)(void *)((char *)(ap) - __VA_ALIGNED_SIZE(type)) )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/stdbool.h b/include/stdbool.h
new file mode 100644 (file)
index 0000000..3d8fbf2
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _STDBOOL_H
+#define _STDBOOL_H
+
+#ifndef __cplusplus
+
+#define true 1
+#define false 0
+
+typedef _Bool bool;
+
+#endif
+
+#endif
diff --git a/include/stddef.h b/include/stddef.h
new file mode 100644 (file)
index 0000000..dbf5a4a
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+#define __NEED_ptrdiff_t
+#define __NEED_size_t
+#define __NEED_wchar_t
+
+#include <bits/alltypes.h>
+
+#define offsetof(type, member) ((size_t)( (char *)&(((type *)0)->member) - (char *)0 ))
+
+#endif
diff --git a/include/stdint.h b/include/stdint.h
new file mode 100644 (file)
index 0000000..4d24fd2
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef _STDINT_H
+#define _STDINT_H
+
+#define __NEED_int8_t
+#define __NEED_int16_t
+#define __NEED_int32_t
+#define __NEED_int64_t
+
+#define __NEED_uint8_t
+#define __NEED_uint16_t
+#define __NEED_uint32_t
+#define __NEED_uint64_t
+
+#define __NEED_int_least8_t
+#define __NEED_int_least16_t
+#define __NEED_int_least32_t
+#define __NEED_int_least64_t
+
+#define __NEED_uint_least8_t
+#define __NEED_uint_least16_t
+#define __NEED_uint_least32_t
+#define __NEED_uint_least64_t
+
+#define __NEED_int_fast8_t
+#define __NEED_int_fast16_t
+#define __NEED_int_fast32_t
+#define __NEED_int_fast64_t
+
+#define __NEED_uint_fast8_t
+#define __NEED_uint_fast16_t
+#define __NEED_uint_fast32_t
+#define __NEED_uint_fast64_t
+
+#define __NEED_intptr_t
+#define __NEED_uintptr_t
+#define __NEED_intmax_t
+#define __NEED_uintmax_t
+
+#include <bits/alltypes.h>
+
+#if !defined __cplusplus || defined __STDC_LIMIT_MACROS
+
+#define INT8_MIN   (-1-0x7f)
+#define INT16_MIN  (-1-0x7fff)
+#define INT32_MIN  (-1-0x7fffffff)
+#define INT64_MIN  (-1-0x7fffffffffffffffLL)
+
+#define INT8_MAX   (0x7f)
+#define INT16_MAX  (0x7fff)
+#define INT32_MAX  (0x7fffffff)
+#define INT64_MAX  (0x7fffffffffffffffLL)
+
+#define UINT8_MAX  (0xff)
+#define UINT16_MAX (0xffff)
+#define UINT32_MAX (0xffffffff)
+#define UINT64_MAX (0xffffffffffffffffULL)
+
+#define INT_LEAST8_MIN   INT8_MIN
+#define INT_LEAST16_MIN  INT16_MIN
+#define INT_LEAST32_MIN  INT32_MIN
+#define INT_LEAST64_MIN  INT64_MIN
+
+#define INT_LEAST8_MAX   INT8_MAX
+#define INT_LEAST16_MAX  INT16_MAX
+#define INT_LEAST32_MAX  INT32_MAX
+#define INT_LEAST64_MAX  INT64_MAX
+
+#define UINT_LEAST8_MAX  UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+#undef WCHAR_MIN
+#undef WCHAR_MAX
+#undef WINT_MIN
+#undef WINT_MAX
+#define WCHAR_MIN INT32_MIN
+#define WCHAR_MAX INT32_MAX
+#define WINT_MIN INT32_MIN
+#define WINT_MAX INT32_MAX
+
+#define INTMAX_MIN  INT64_MIN
+#define INTMAX_MAX  INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+#include <bits/stdint.h>
+
+#endif
+
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+
+#define INT8_C(c)  c
+#define INT16_C(c) c
+#define INT32_C(c) c
+#define INT64_C(c) c ## LL
+
+#define UINT8_C(c)  c ## U
+#define UINT16_C(c) c ## U
+#define UINT32_C(c) c ## U
+#define UINT64_C(c) c ## ULL
+
+#define INTMAX_C(c)  c ## LL
+#define UINTMAX_C(c) c ## ULL
+
+#endif
+
+#endif
diff --git a/include/stdio.h b/include/stdio.h
new file mode 100644 (file)
index 0000000..b00436d
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_FILE
+#define __NEED_va_list
+#define __NEED_size_t
+#define __NEED_ssize_t
+#define __NEED_off_t
+
+#include <bits/alltypes.h>
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+#undef EOF
+#define EOF (-1)
+
+#undef SEEK_SET
+#undef SEEK_CUR
+#undef SEEK_END
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#define _IOFBF 0
+#define _IOLBF 1
+#define _IONBF 2
+
+#include <bits/stdio.h>
+
+typedef union {
+       char __opaque[16];
+       double __align;
+} fpos_t;
+
+extern FILE *const stdin;
+extern FILE *const stdout;
+extern FILE *const stderr;
+
+#define stdin  (stdin)
+#define stdout (stdout)
+#define stderr (stderr)
+
+FILE *fopen(const char *, const char *);
+FILE *fdopen(int, const char *);
+FILE *freopen(const char *, const char *, FILE *);
+int fclose(FILE *);
+
+FILE *popen(const char *, const char *);
+int pclose(FILE *);
+
+int remove(const char *);
+int rename(const char *, const char *);
+
+int fileno(FILE *);
+int feof(FILE *);
+int ferror(FILE *);
+int fflush(FILE *);
+void clearerr(FILE *);
+
+int fseek(FILE *, long, int);
+int fseeko(FILE *, off_t, int);
+long ftell(FILE *);
+off_t ftello(FILE *);
+void rewind(FILE *);
+
+int fgetpos(FILE *, fpos_t *);
+int fsetpos(FILE *, const fpos_t *);
+
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *, size_t, size_t, FILE *);
+
+int fgetc(FILE *);
+int getc(FILE *);
+int getchar(void);
+int ungetc(int, FILE *);
+
+int fputc(int, FILE *);
+int putc(int, FILE *);
+int putchar(int);
+
+char *fgets(char *, int, FILE *);
+char *gets(char *);
+
+int fputs(const char *, FILE *);
+int puts(const char *);
+
+int printf(const char *, ...);
+int fprintf(FILE *, const char *, ...);
+int sprintf(char *, const char *, ...);
+int snprintf(char *, size_t, const char *, ...);
+
+int vprintf(const char *, va_list);
+int vfprintf(FILE *, const char *, va_list);
+int vsprintf(char *, const char *, va_list);
+int vsnprintf(char *, size_t, const char *, va_list);
+
+int dprintf(int, const char *, ...);
+int vdprintf(int, const char *, va_list);
+
+int scanf(const char *, ...);
+int fscanf(FILE *, const char *, ...);
+int sscanf(const char *, const char *, ...);
+int vscanf(const char *, va_list);
+int vfscanf(FILE *, const char *, va_list);
+int vsscanf(const char *, const char *, va_list);
+
+void perror(const char *);
+
+void flockfile(FILE *);
+int ftrylockfile(FILE *);
+void funlockfile(FILE *);
+int getc_unlocked(FILE *);
+int getchar_unlocked(void);
+int putc_unlocked(int, FILE *);
+int putchar_unlocked(int);
+
+int setvbuf(FILE *, char *, int, size_t);
+void setbuf(FILE *, char *);
+
+char *tmpnam(char *);
+char *tempnam(const char *, const char *);
+FILE *tmpfile(void);
+
+char *ctermid(char *);
+
+ssize_t getdelim(char **, size_t *, int, FILE *);
+ssize_t getline(char **, size_t *, FILE *);
+
+int renameat(int, const char *, int, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/stdlib.h b/include/stdlib.h
new file mode 100644 (file)
index 0000000..6dbbc9c
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+#define __NEED_size_t
+#define __NEED_wchar_t
+
+#include <bits/alltypes.h>
+
+int atoi (const char *);
+long atol (const char *);
+long long atoll (const char *);
+double atof (const char *);
+
+float strtof (const char *, char **);
+double strtod (const char *, char **);
+long double strtold (const char *, char **);
+
+long strtol (const char *, char **, int);
+unsigned long strtoul (const char *, char **, int);
+
+long long strtoll (const char *, char **, int);
+unsigned long long strtoull (const char *, char **, int);
+
+char *l64a (long);
+long a64l (const char *);
+
+long int random (void);
+void srandom (unsigned int);
+char *initstate (unsigned int, char *, size_t);
+char *setstate (char *);
+
+int rand (void);
+void srand (unsigned);
+int rand_r (unsigned *);
+
+double drand48 (void);
+double erand48 (unsigned short [3]);
+long int lrand48 (void);
+long int nrand48 (unsigned short [3]);
+long mrand48 (void);
+long jrand48 (unsigned short [3]);
+void srand48 (long);
+unsigned short *seed48 (unsigned short [3]);
+void lcong48 (unsigned short [7]);
+
+void *malloc (size_t);
+void *calloc (size_t, size_t);
+void *realloc (void *, size_t);
+void free (void *);
+void *valloc (size_t);
+int posix_memalign (void **, size_t, size_t);
+
+void abort (void);
+int atexit (void (*) (void));
+void exit (int);
+void _Exit (int);
+
+
+char *getenv (const char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+int unsetenv (const char *);
+
+
+char *mktemp (char *);
+int mkstemp (char *);
+
+int system (const char *);
+
+
+char *realpath (const char *, char *);
+
+void *bsearch (const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
+void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
+
+int abs (int);
+long labs (long);
+long long llabs (long long);
+
+typedef struct { int quot, rem; } div_t;
+extern div_t div (int, int);
+
+typedef struct { long quot, rem; } ldiv_t;
+ldiv_t ldiv (long, long);
+
+typedef struct { long long quot, rem; } lldiv_t;
+lldiv_t lldiv (long long, long long);
+
+
+int mblen (const char *, size_t);
+int mbtowc (wchar_t *, const char *, size_t);
+int wctomb (char *, wchar_t);
+size_t mbstowcs (wchar_t *, const char *, size_t);
+size_t wcstombs (char *, const wchar_t *, size_t);
+
+int getsubopt (char **, char *const *, char **);
+
+void setkey (const char *);
+
+int posix_openpt (int);
+int grantpt (int);
+int unlockpt (int);
+char *ptsname (int);
+
+#define MB_CUR_MAX 4
+
+#define RAND_MAX (0x7fffffff)
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+#include <bits/wexitstatus.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/string.h b/include/string.h
new file mode 100644 (file)
index 0000000..f189c08
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef        _STRING_H
+#define        _STRING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+#define __NEED_size_t
+#include <bits/alltypes.h>
+
+void *memcpy (void *, const void *, size_t);
+void *memmove (void *, const void *, size_t);
+void *memccpy (void *, const void *, int, size_t);
+void *memset (void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+void *memchr (const void *, int, size_t);
+
+char *strcpy (char *, const char *);
+char *strncpy (char *, const char *, size_t);
+
+char *strcat (char *, const char *);
+char *strncat (char *, const char *, size_t);
+
+int strcmp (const char *, const char *);
+int strncmp (const char *, const char *, size_t);
+
+int strcoll (const char *, const char *);
+size_t strxfrm (char *, const char *, size_t);
+
+char *strdup (const char *);
+
+char *strchr (const char *, int);
+char *strrchr (const char *, int);
+
+size_t strcspn (const char *, const char *);
+size_t strspn (const char *, const char *);
+char *strpbrk (const char *, const char *);
+char *strstr (const char *, const char *);
+
+char *strtok (char *, const char *);
+char *strtok_r (char *, const char *, char **);
+
+size_t strlen (const char *);
+
+char *strerror (int);
+int strerror_r (int, char *, size_t);
+
+size_t strlcat (char *, const char *, size_t);
+size_t strlcpy (char *, const char *, size_t);
+
+char *stpcpy(char *, const char *);
+char *stpncpy(char *, const char *, size_t);
+size_t strnlen (const char *, size_t);
+
+#ifdef _GNU_SOURCE
+int strcasecmp (const char *, const char *);
+int strncasecmp (const char *, const char *, size_t);
+char *strchrnul(const char *, int);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/strings.h b/include/strings.h
new file mode 100644 (file)
index 0000000..059e330
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef        _STRINGS_H
+#define        _STRINGS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+
+#define __NEED_size_t
+#include <bits/alltypes.h>
+
+
+int bcmp (const void *, const void *, size_t);
+void bcopy (const void *, void *, size_t);
+void bzero (void *, size_t);
+
+int ffs (int);
+
+char *index (const char *, int);
+char *rindex (const char *, int);
+
+int strcasecmp (const char *, const char *);
+int strncasecmp (const char *, const char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/stropts.h b/include/stropts.h
new file mode 100644 (file)
index 0000000..80776ba
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _STROPTS_H
+#define _STROPTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// FIXME
+
+int ioctl (int, int, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sys/epoll.h b/include/sys/epoll.h
new file mode 100644 (file)
index 0000000..3530a9a
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef        _SYS_EPOLL_H
+#define        _SYS_EPOLL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#define __NEED_sigset_t
+
+#include <bits/alltypes.h>
+
+#define EPOLL_CLOEXEC 02000000
+#define EPOLL_NONBLOCK 04000
+
+enum EPOLL_EVENTS { __EPOLL_DUMMY };
+#define EPOLLIN 0x001
+#define EPOLLPRI 0x002
+#define EPOLLOUT 0x004
+#define EPOLLRDNORM 0x040
+#define EPOLLRDBAND 0x080
+#define EPOLLWRNORM 0x100
+#define EPOLLWRBAND 0x200
+#define EPOLLMSG 0x400
+#define EPOLLERR 0x008
+#define EPOLLHUP 0x010
+#define EPOLLRDHUP 0x2000
+#define EPOLLONESHOT (1U<<30)
+#define EPOLLET (1U<<31)
+
+#define EPOLL_CTL_ADD 1
+#define EPOLL_CTL_DEL 2
+#define EPOLL_CTL_MOD 3
+
+typedef union epoll_data {
+       void *ptr;
+       int fd;
+       uint32_t u32;
+       uint64_t u64;
+} epoll_data_t;
+
+struct epoll_event {
+       uint32_t events;
+       epoll_data_t data;
+} __attribute__ ((__packed__));
+
+
+int epoll_create(int);
+int epoll_create1(int);
+int epoll_ctl(int, int, int, struct epoll_event *);
+int epoll_wait(int, struct epoll_event *, int, int);
+int epoll_pwait(int, struct epoll_event *, int, int, const sigset_t *);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sys/epoll.h */
diff --git a/include/sys/file.h b/include/sys/file.h
new file mode 100644 (file)
index 0000000..8b2eb01
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _SYS_FILE_H
+#define _SYS_FILE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#define LOCK_SH        1
+#define LOCK_EX        2
+#define LOCK_NB        4
+#define LOCK_UN        8
+
+extern int flock(int, int);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/ioctl.h b/include/sys/ioctl.h
new file mode 100644 (file)
index 0000000..d0415b3
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef        _SYS_IOCTL_H
+#define        _SYS_IOCTL_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bits/ioctl.h>
+
+int ioctl (int, int, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/ipc.h b/include/sys/ipc.h
new file mode 100644 (file)
index 0000000..9de9f3e
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _SYS_IPC_H
+#define _SYS_IPC_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_uid_t
+#define __NEED_gid_t
+#define __NEED_mode_t
+#define __NEED_key_t
+
+#include <bits/alltypes.h>
+
+#include <bits/ipc.h>
+
+key_t ftok (const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/include/sys/kd.h b/include/sys/kd.h
new file mode 100644 (file)
index 0000000..793fd59
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _SYS_KD_H
+#define _SYS_KD_H
+
+#define _LINUX_TYPES_H
+#include <linux/kd.h>
+#undef _LINUX_TYPES_H
+
+#endif
diff --git a/include/sys/klog.h b/include/sys/klog.h
new file mode 100644 (file)
index 0000000..aa66684
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef        _SYS_KLOG_H
+#define        _SYS_KLOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int klogctl (int, char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sys/mman.h b/include/sys/mman.h
new file mode 100644 (file)
index 0000000..6aede8b
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef        _SYS_MMAN_H
+#define        _SYS_MMAN_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_mode_t
+#define __NEED_size_t
+#define __NEED_off_t
+
+#include <bits/alltypes.h>
+
+#include <bits/mman.h>
+
+void *mmap (void *, size_t, int, int, int, off_t);
+int munmap (void *, size_t);
+
+int mprotect (void *, size_t, int);
+int msync (void *, size_t, int);
+
+int posix_madvise (void *, size_t, int);
+
+int mlock (const void *, size_t);
+int munlock (const void *, size_t);
+int mlockall (int);
+int munlockall (void);
+
+/* linux extension */
+void *mremap (void *, size_t, size_t, int, ...);
+
+int shm_open (const char *, int, mode_t);
+int shm_unlink (const char *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/mount.h b/include/sys/mount.h
new file mode 100644 (file)
index 0000000..2c685f6
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _SYS_MOUNT_H
+#define _SYS_MOUNT_H
+
+#define MS_RDONLY      1
+#define MS_NOSUID      2
+#define MS_NODEV       4
+#define MS_NOEXEC      8
+#define MS_SYNCHRONOUS 16
+#define MS_REMOUNT     32
+#define MS_MANDLOCK    64
+#define S_WRITE        128
+#define S_APPEND       256
+#define S_IMMUTABLE    512
+#define MS_NOATIME     1024
+#define MS_NODIRATIME  2048
+#define MS_BIND        4096
+#define MS_MOVE        8192
+#define MS_SILENT      32768
+
+#define MS_MGC_VAL 0xc0ed0000
+
+#define MNT_FORCE 1
+
+int mount(const char *, const char *, const char *, unsigned long, const void *);
+int umount(const char *);
+int umount2(const char *, int);
+
+#endif
diff --git a/include/sys/msg.h b/include/sys/msg.h
new file mode 100644 (file)
index 0000000..9fc42bc
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _SYS_MSG_H
+#define _SYS_MSG_H
+
+#include <sys/ipc.h>
+
+#define __NEED_pid_t
+#define __NEED_key_t
+#define __NEED_time_t
+#define __NEED_size_t
+#define __NEED_ssize_t
+
+#include <bits/alltypes.h>
+
+typedef unsigned long msgqnum_t;
+typedef unsigned long msglen_t;
+
+struct msqid_ds
+{
+       struct ipc_perm msg_perm;
+       time_t msg_stime;
+       time_t msg_rtime;
+       time_t msg_ctime;
+       msgqnum_t msg_qnum;
+       msglen_t msg_qbytes;
+       pid_t msg_lspid;
+       pid_t msd_lrpid;
+};
+
+#define MSG_NOERROR 010000
+
+int msgctl (int, int, struct msqid_ds *);
+int msgget (key_t, int);
+int msgrcv (int, void *, size_t, long, int);
+int msgsnd (int, const void *, size_t, int);
+
+#endif
diff --git a/include/sys/param.h b/include/sys/param.h
new file mode 100644 (file)
index 0000000..ded4a16
--- /dev/null
@@ -0,0 +1,15 @@
+#undef MAXSYMLINKS
+#define MAXSYMLINKS 20
+
+#undef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+
+#undef MAXNAMLEN
+#define MAXNAMLEN NAME_MAX
+
+#undef MAXPATHLEN
+#define MAXPATHLEN PATH_MAX
+
+#include <sys/resource.h>
+#include <endian.h>
+#include <limits.h>
diff --git a/include/sys/poll.h b/include/sys/poll.h
new file mode 100644 (file)
index 0000000..779ec77
--- /dev/null
@@ -0,0 +1 @@
+#include <poll.h>
diff --git a/include/sys/prctl.h b/include/sys/prctl.h
new file mode 100644 (file)
index 0000000..cd34848
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _SYS_PRCTL_H
+#define _SYS_PRCTL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PR_SET_PDEATHSIG  1
+#define PR_GET_PDEATHSIG  2
+#define PR_GET_DUMPABLE   3
+#define PR_SET_DUMPABLE   4
+#define PR_GET_UNALIGN   5
+#define PR_SET_UNALIGN   6
+#define PR_UNALIGN_NOPRINT 1
+#define PR_UNALIGN_SIGBUS 2
+#define PR_GET_KEEPCAPS   7
+#define PR_SET_KEEPCAPS   8
+#define PR_GET_FPEMU  9
+#define PR_SET_FPEMU 10
+#define PR_FPEMU_NOPRINT 1
+#define PR_FPEMU_SIGFPE 2
+#define PR_GET_FPEXC 11
+#define PR_SET_FPEXC 12
+#define PR_FP_EXC_SW_ENABLE 0x80
+#define PR_FP_EXC_DIV  0x010000
+#define PR_FP_EXC_OVF  0x020000
+#define PR_FP_EXC_UND  0x040000
+#define PR_FP_EXC_RES  0x080000
+#define PR_FP_EXC_INV  0x100000
+#define PR_FP_EXC_DISABLED 0
+#define PR_FP_EXC_NONRECOV 1
+#define PR_FP_EXC_ASYNC 2
+#define PR_FP_EXC_PRECISE 3
+#define PR_GET_TIMING   13
+#define PR_SET_TIMING   14
+#define PR_TIMING_STATISTICAL  0
+#define PR_TIMING_TIMESTAMP    1
+#define PR_SET_NAME    15
+#define PR_GET_NAME    16
+#define PR_GET_ENDIAN 19
+#define PR_SET_ENDIAN 20
+#define PR_ENDIAN_BIG
+#define PR_ENDIAN_LITTLE
+#define PR_ENDIAN_PPC_LITTLE
+#define PR_GET_SECCOMP 21
+#define PR_SET_SECCOMP 22
+#define PR_CAPBSET_READ 23
+#define PR_CAPBSET_DROP 24
+#define PR_GET_TSC 25
+#define PR_SET_TSC 26
+#define PR_TSC_ENABLE 1
+#define PR_TSC_SIGSEGV 2
+#define PR_GET_SECUREBITS 27
+#define PR_SET_SECUREBITS 28
+#define PR_SET_TIMERSLACK 29
+#define PR_GET_TIMERSLACK 30
+
+int prctl (int, ...);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif
diff --git a/include/sys/procfs.h b/include/sys/procfs.h
new file mode 100644 (file)
index 0000000..20b4847
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef _SYS_PROCFS_H
+#define _SYS_PROCFS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+#if __WORDSIZE == 32
+typedef struct user_fpregs_struct elf_fpregset_t;
+typedef struct user_fpxregs_struct elf_fpxregset_t;
+#else
+typedef struct user_fpregs_struct elf_fpregset_t;
+#endif
+
+struct elf_siginfo {
+       int si_signo;
+       int si_code;
+       int si_errno;
+};
+
+struct elf_prstatus {
+       struct elf_siginfo pr_info;
+       short int pr_cursig;
+       unsigned long int pr_sigpend;
+       unsigned long int pr_sighold;
+       pid_t pr_pid;
+       pid_t pr_ppid;
+       pid_t pr_pgrp;
+       pid_t pr_sid;
+       struct timeval pr_utime;
+       struct timeval pr_stime;
+       struct timeval pr_cutime;
+       struct timeval pr_cstime;
+       elf_gregset_t pr_reg;
+       int pr_fpvalid;
+};
+
+
+#define ELF_PRARGSZ 80
+
+struct elf_prpsinfo
+       {
+       char pr_state;
+       char pr_sname;
+       char pr_zomb;
+       char pr_nice;
+       unsigned long int pr_flag;
+#if __WORDSIZE == 32
+       unsigned short int pr_uid;
+       unsigned short int pr_gid;
+#else
+       unsigned int pr_uid;
+       unsigned int pr_gid;
+#endif
+       int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+       char pr_fname[16];
+       char pr_psargs[ELF_PRARGSZ];
+};
+
+
+typedef void *psaddr_t;
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+typedef pid_t lwpid_t;
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h
new file mode 100644 (file)
index 0000000..0459d1b
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _SYS_PTRACE_H
+#define _SYS_PTRACE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PTRACE_TRACEME 0
+#define PT_TRACE_ME PTRACE_TRACEME
+
+#define PTRACE_PEEKTEXT 1
+#define PTRACE_PEEKDATA 2
+#define PTRACE_PEEKUSER 3
+#define PTRACE_POKETEXT 4
+#define PTRACE_POKEDATA 5
+#define PTRACE_POKEUSER 6
+#define PTRACE_CONT 7
+#define PTRACE_KILL 8
+#define PTRACE_SINGLESTEP 9
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_ATTACH 16
+#define PTRACE_DETACH 17
+#define PTRACE_GETFPXREGS 18
+#define PTRACE_SETFPXREGS 19
+#define PTRACE_SYSCALL 24
+#define PTRACE_SETOPTIONS 0x4200
+#define PTRACE_GETEVENTMSG 0x4201
+#define PTRACE_GETSIGINFO 0x4202
+#define PTRACE_SETSIGINFO 0x4203
+
+#define PT_READ_I PTRACE_PEEKTEXT
+#define PT_READ_D PTRACE_PEEKDATA
+#define PT_READ_U PTRACE_PEEKUSER
+#define PT_WRITE_I PTRACE_POKETEXT
+#define PT_WRITE_D PTRACE_POKEDATA
+#define PT_WRITE_U PTRACE_POKEUSER
+#define PT_CONTINUE PTRACE_CONT
+#define PT_KILL PTRACE_KILL
+#define PT_STEP PTRACE_SINGLESTEP
+#define PT_GETREGS PTRACE_GETREGS
+#define PT_SETREGS PTRACE_SETREGS
+#define PT_GETFPREGS PTRACE_GETFPREGS
+#define PT_SETFPREGS PTRACE_SETFPREGS
+#define PT_ATTACH PTRACE_ATTACH
+#define PT_DETACH PTRACE_DETACH
+#define PT_GETFPXREGS PTRACE_GETFPXREGS
+#define PT_SETFPXREGS PTRACE_SETFPXREGS
+#define PT_SYSCALL PTRACE_SYSCALL
+#define PT_SETOPTIONS PTRACE_SETOPTIONS
+#define PT_GETEVENTMSG PTRACE_GETEVENTMSG
+#define PT_GETSIGINFO PTRACE_GETSIGINFO
+#define PT_SETSIGINFO PTRACE_SETSIGINFO
+
+#define PTRACE_O_TRACESYSGOOD   0x00000001
+#define PTRACE_O_TRACEFORK      0x00000002
+#define PTRACE_O_TRACEVFORK     0x00000004
+#define PTRACE_O_TRACECLONE     0x00000008
+#define PTRACE_O_TRACEEXEC      0x00000010
+#define PTRACE_O_TRACEVFORKDONE 0x00000020
+#define PTRACE_O_TRACEEXIT      0x00000040
+#define PTRACE_O_MASK           0x0000007f
+
+#define PTRACE_EVENT_FORK 1
+#define PTRACE_EVENT_VFORK 2
+#define PTRACE_EVENT_CLONE 3
+#define PTRACE_EVENT_EXEC 4
+#define PTRACE_EVENT_VFORK_DONE 5
+#define PTRACE_EVENT_EXIT 6
+
+long int ptrace(int, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/reboot.h b/include/sys/reboot.h
new file mode 100644 (file)
index 0000000..26cc308
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _SYS_REBOOT_H
+#define _SYS_REBOOT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RB_AUTOBOOT     0x01234567
+#define RB_HALT_SYSTEM  0xcdef0123
+#define RB_ENABLE_CAD   0x89abcdef
+#define RB_DISABLE_CAD  0
+#define RB_POWER_OFF    0x4321fedc
+
+int reboot(int);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/reg.h b/include/sys/reg.h
new file mode 100644 (file)
index 0000000..ebf3fff
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _SYS_USER_H
+#define _SYS_USER_H
+
+#include <limits.h>
+#include <unistd.h>
+
+#include <bits/reg.h>
+
+#endif
diff --git a/include/sys/resource.h b/include/sys/resource.h
new file mode 100644 (file)
index 0000000..99e383c
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef        _SYS_RESOURCE_H
+#define        _SYS_RESOURCE_H
+
+#define __NEED_id_t
+#define __NEED_time_t
+#define __NEED_struct_timeval
+#define __NEED_struct_rusage
+
+#include <bits/alltypes.h>
+
+typedef unsigned long long rlim_t;
+
+struct rlimit
+{
+       rlim_t rlim_cur;
+       rlim_t rlim_max;
+};
+
+struct rusage
+{
+       struct timeval ru_utime;
+       struct timeval ru_stime;
+       /* linux extentions, but useful */
+       long    ru_maxrss;
+       long    ru_ixrss;
+       long    ru_idrss;
+       long    ru_isrss;
+       long    ru_minflt;
+       long    ru_majflt;
+       long    ru_nswap;
+       long    ru_inblock;
+       long    ru_oublock;
+       long    ru_msgsnd;
+       long    ru_msgrcv;
+       long    ru_nsignals;
+       long    ru_nvcsw;
+       long    ru_nivcsw;
+       /* room for more... */
+       long    __reserved[16];
+};
+
+int getrlimit (int, struct rlimit *);
+int setrlimit (int, const struct rlimit *);
+int getrusage (int, struct rusage *);
+
+int getpriority (int, id_t);
+int setpriority (int, id_t, int);
+
+#define PRIO_PROCESS 0
+#define PRIO_PGRP    1
+#define PRIO_USER    2
+
+#define RUSAGE_SELF     0
+#define RUSAGE_CHILDREN 1
+
+#define RLIM_INFINITY (~0ULL)
+#define RLIM_SAVED_CUR RLIM_INFINITY
+#define RLIM_SAVED_MAX RLIM_INFINITY
+
+#define RLIMIT_CPU     0
+#define RLIMIT_FSIZE   1
+#define RLIMIT_DATA    2
+#define RLIMIT_STACK   3
+#define RLIMIT_CORE    4
+#define RLIMIT_RSS     5
+#define RLIMIT_NOFILE  7
+#define RLIMIT_AS      9
+#define RLIMIT_NPROC   6
+#define RLIMIT_MEMLOCK 8
+#define RLIMIT_LOCKS   10
+
+
+
+#endif
diff --git a/include/sys/select.h b/include/sys/select.h
new file mode 100644 (file)
index 0000000..c44eada
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _SYS_SELECT_H
+#define _SYS_SELECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+#define __NEED_time_t
+#define __NEED_struct_timeval
+#define __NEED_struct_timespec
+#define __NEED_sigset_t
+
+#include <bits/alltypes.h>
+
+#define FD_SETSIZE 1024
+
+typedef struct
+{
+       unsigned long fds_bits[FD_SETSIZE / 8 / sizeof(long)];
+} fd_set;
+
+#define FD_ZERO(s) do { int __i; unsigned long *__b=(s)->fds_bits; for(__i=sizeof (fd_set)/sizeof (long); __i; __i--) *__b++=0; } while(0)
+#define FD_SET(d, s)   ((s)->fds_bits[(d)/(8*sizeof(long))] |= (1<<((d)%(8*sizeof(long)))))
+#define FD_CLR(d, s)   ((s)->fds_bits[(d)/(8*sizeof(long))] &= ~(1<<((d)%(8*sizeof(long)))))
+#define FD_ISSET(d, s) ((s)->fds_bits[(d)/(8*sizeof(long))] & (1<<((d)%(8*sizeof(long)))))
+
+int select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
+int pselect (int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/sem.h b/include/sys/sem.h
new file mode 100644 (file)
index 0000000..15d8b68
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef _SYS_SEM_H
+#define _SYS_SEM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+#include <bits/alltypes.h>
+
+#include <sys/ipc.h>
+
+#define SEM_UNDO       0x1000
+#define GETPID         11
+#define GETVAL         12
+#define GETALL         13
+#define GETNCNT                14
+#define GETZCNT                15
+#define SETVAL         16
+#define SETALL         17
+
+struct semid_ds {
+       struct ipc_perm sem_perm;
+       long sem_otime;
+       unsigned long __unused1;
+       long sem_ctime;
+       unsigned long __unused2;
+       unsigned long sem_nsems;
+       unsigned long __unused3;
+       unsigned long __unused4;
+};
+
+#define _SEM_SEMUN_UNDEFINED 1
+
+#define SEM_STAT 18
+#define SEM_INFO 19
+
+struct  seminfo {
+       int semmap;
+       int semmni;
+       int semmns;
+       int semmnu;
+       int semmsl;
+       int semopm;
+       int semume;
+       int semusz;
+       int semvmx;
+       int semaem;
+};
+
+struct sembuf {
+       unsigned short sem_num;
+       short sem_op;
+       short sem_flg;
+};
+
+int semctl(int, int, int, ...);
+int semget(key_t, int, int);
+int semop(int, struct sembuf *, size_t);
+
+#ifdef _GNU_SOURCE
+#define __NEED_struct_timespec
+#include <bits/alltypes.h>
+int semtimedop(int, struct sembuf *, size_t, const struct timespec *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/shm.h b/include/sys/shm.h
new file mode 100644 (file)
index 0000000..6ebb941
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _SYS_SHM_H
+#define _SYS_SHM_H
+
+#define __NEED_time_t
+#define __NEED_size_t
+#define __NEED_pid_t
+
+#include <bits/alltypes.h>
+
+#include <sys/ipc.h>
+#include <bits/shm.h>
+
+void *shmat(int, const void *, int);
+int shmctl(int, int, struct shmid_ds *);
+int shmdt(const void *);
+int shmget(key_t, size_t, int);
+
+#endif
diff --git a/include/sys/signalfd.h b/include/sys/signalfd.h
new file mode 100644 (file)
index 0000000..895664b
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _SYS_SIGNALFD_H
+#define _SYS_SIGNALFD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define __NEED_sigset_t
+
+#include <bits/alltypes.h>
+
+int signalfd(int, const sigset_t *, int);
+
+struct signalfd_siginfo {
+       uint32_t  ssi_signo;
+       int32_t   ssi_errno;
+       int32_t   ssi_code;
+       uint32_t  ssi_pid;
+       uint32_t  ssi_uid;
+       int32_t   ssi_fd;
+       uint32_t  ssi_tid;
+       uint32_t  ssi_band;
+       uint32_t  ssi_overrun;
+       uint32_t  ssi_trapno;
+       int32_t   ssi_status;
+       int32_t   ssi_int;
+       uintptr_t ssi_ptr;
+       uint64_t  ssi_utime;
+       uint64_t  ssi_stime;
+       uint64_t  ssi_addr;
+       uint8_t   pad[128-12*4-sizeof(void *)-3*8];
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sys/socket.h b/include/sys/socket.h
new file mode 100644 (file)
index 0000000..78c9305
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef        _SYS_SOCKET_H
+#define        _SYS_SOCKET_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_socklen_t
+#define __NEED_sa_family_t
+#define __NEED_size_t
+#define __NEED_ssize_t
+#define __NEED_uid_t
+#define __NEED_pid_t
+#define __NEED_gid_t
+
+#include <bits/alltypes.h>
+
+#include <bits/socket.h>
+
+struct sockaddr
+{
+       sa_family_t sa_family;
+       char sa_data[14];
+};
+
+struct sockaddr_storage
+{
+       sa_family_t ss_family;
+       long long __ss_align;
+       char __ss_padding[128 - sizeof(sa_family_t) - sizeof(long long)];
+};
+
+int socket (int, int, int);
+int socketpair (int, int, int, int [2]);
+
+int shutdown (int, int);
+
+int bind (int, const struct sockaddr *, socklen_t);
+int connect (int, const struct sockaddr *, socklen_t);
+int listen (int, int);
+int accept (int, struct sockaddr *, socklen_t *);
+
+int getsockname (int, struct sockaddr *, socklen_t *);
+int getpeername (int, struct sockaddr *, socklen_t *);
+
+ssize_t send (int, const void *, size_t, int);
+ssize_t recv (int, void *, size_t, int);
+ssize_t sendto (int, const void *, size_t, int, const struct sockaddr *, socklen_t);
+ssize_t recvfrom (int, void *, size_t, int, struct sockaddr *, socklen_t *);
+ssize_t sendmsg (int, const struct msghdr *, int);
+ssize_t recvmsg (int, struct msghdr *, int);
+
+int getsockopt (int, int, int, void *, socklen_t *);
+int setsockopt (int, int, int, const void *, socklen_t);
+
+int sockatmark (int);
+
+#define SHUT_RD 0
+#define SHUT_WR 1
+#define SHUT_RDWR 2
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/soundcard.h b/include/sys/soundcard.h
new file mode 100644 (file)
index 0000000..fade986
--- /dev/null
@@ -0,0 +1 @@
+#include <linux/soundcard.h>
diff --git a/include/sys/stat.h b/include/sys/stat.h
new file mode 100644 (file)
index 0000000..36575b0
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef        _SYS_STAT_H
+#define        _SYS_STAT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_dev_t
+#define __NEED_ino_t
+#define __NEED_mode_t
+#define __NEED_nlink_t
+#define __NEED_uid_t
+#define __NEED_gid_t
+#define __NEED_off_t
+#define __NEED_time_t
+#define __NEED_blksize_t
+#define __NEED_blkcnt_t
+
+#include <bits/alltypes.h>
+
+#include <bits/stat.h>
+
+#define S_IFMT  0170000
+
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFBLK 0060000
+#define S_IFREG 0100000
+#define S_IFIFO 0010000
+#define S_IFLNK 0120000
+#define S_IFSOCK 0140000
+
+#define S_TYPEISMQ(buf)  0
+#define S_TYPEISSEM(buf) 0
+#define S_TYPEISSHM(buf) 0
+#define S_TYPEISTMO(buf) 0
+
+#define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
+#define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
+#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#define S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
+#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+
+#define S_ISUID 04000
+#define S_ISGID 02000
+#define S_ISVTX 01000
+
+#define S_IREAD  0400
+#define S_IWRITE 0200
+#define S_IEXEC  0100
+
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define S_IXUSR 0100
+#define S_IRWXU 0700
+
+#define S_IRGRP 0040
+#define S_IWGRP 0020
+#define S_IXGRP 0010
+#define S_IRWXG 0070
+
+#define S_IROTH 0004
+#define S_IWOTH 0002
+#define S_IXOTH 0001
+#define S_IRWXO 0007
+
+
+int stat(const char *, struct stat *);
+int fstat(int, struct stat *);
+int lstat(const char *, struct stat *);
+int fstatat(int, const char *, struct stat *, int);
+int chmod(const char *, mode_t);
+int fchmod(int, mode_t);
+int fchmodat(int, const char *, mode_t, int);
+mode_t umask(mode_t);
+int mkdir(const char *, mode_t);
+int mknod(const char *, mode_t, dev_t);
+int mkfifo(const char *, mode_t);
+int mkdirat(int, const char *, mode_t);
+int mknodat(int, const char *, mode_t, dev_t);
+int mkfifoat(int, const char *, mode_t);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/include/sys/statfs.h b/include/sys/statfs.h
new file mode 100644 (file)
index 0000000..7eaa7e7
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef        _SYS_STATFS_H
+#define        _SYS_STATFS_H
+
+#include <sys/statvfs.h>
+
+#define statfs statvfs
+#define fstatfs fstatvfs
+#define f_namelen f_namemax
+
+#endif
diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h
new file mode 100644 (file)
index 0000000..6479be6
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef        _SYS_STATVFS_H
+#define        _SYS_STATVFS_H
+
+
+#define __NEED_fsblkcnt_t
+#define __NEED_fsfilcnt_t
+#include <bits/alltypes.h>
+
+#include <bits/statfs.h>
+
+int statvfs (const char *, struct statvfs *);
+int fstatvfs (int, struct statvfs *);
+
+#define ST_RDONLY 1
+#define ST_NOSUID 2
+
+#if 0
+#define ST_NODEV  4
+#define ST_NOEXEC 8
+#define ST_SYNCHRONOUS 16
+#define ST_MANDLOCK    64
+#define ST_WRITE       128
+#define ST_APPEND      256
+#define ST_IMMUTABLE   512
+#define ST_NOATIME     1024
+#define ST_NODIRATIME  2048
+#endif
+
+
+#endif
diff --git a/include/sys/stropts.h b/include/sys/stropts.h
new file mode 100644 (file)
index 0000000..5b5bc02
--- /dev/null
@@ -0,0 +1 @@
+#include <stropts.h>
diff --git a/include/sys/swap.h b/include/sys/swap.h
new file mode 100644 (file)
index 0000000..c5824f1
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _SYS_SWAP_H
+#define _SYS_SWAP_H
+
+#define        SWAP_FLAG_PREFER        0x8000
+#define        SWAP_FLAG_PRIO_MASK     0x7fff
+#define        SWAP_FLAG_PRIO_SHIFT    0
+
+int swapon (const char *, int);
+int swapoff (const char *);
+
+#endif
diff --git a/include/sys/sysctl.h b/include/sys/sysctl.h
new file mode 100644 (file)
index 0000000..af5ca8b
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef        _SYS_SYSCTL_H
+#define        _SYS_SYSCTL_H
+
+#define __NEED_size_t
+#include <bits/alltypes.h>
+
+int sysctl (int *, int, void *, size_t *, void *, size_t);
+
+#endif
diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h
new file mode 100644 (file)
index 0000000..ca52088
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _SYS_SYSINFO_H
+#define _SYS_SYSINFO_H
+
+/* ?? */
+#define SI_LOAD_SHIFT 16
+
+struct sysinfo {
+       unsigned long long uptime;
+       unsigned long loads[3];
+       unsigned long procs;
+       unsigned long long totalram;
+       unsigned long long freeram;
+       unsigned long long sharedram;
+       unsigned long long bufferram;
+       unsigned long long totalswap;
+       unsigned long long freeswap;
+       unsigned long long totalhigh;
+       unsigned long long freehigh;
+       unsigned long mem_unit;
+       char __reserved[256];
+};
+
+int sysinfo (struct sysinfo *);
+int get_nprocs_conf (void);
+int get_nprocs (void);
+long long get_phys_pages (void);
+long long get_avphys_pages (void);
+
+#endif
diff --git a/include/sys/sysmacros.h b/include/sys/sysmacros.h
new file mode 100644 (file)
index 0000000..79eba3b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _SYSMACROS_H
+#define _SYSMACROS_H
+
+#include <bits/sysmacros.h>
+
+#endif
diff --git a/include/sys/time.h b/include/sys/time.h
new file mode 100644 (file)
index 0000000..9b3bfb9
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _SYS_TIME_H
+#define _SYS_TIME_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* All symbols from select.h except pselect are required anyway... */
+#include <sys/select.h>
+
+#define __NEED_time_t
+#define __NEED_suseconds_t
+#define __NEED_timeval
+
+#include <bits/alltypes.h>
+
+
+
+int gettimeofday (struct timeval *, void *);
+
+/* extensions */
+int settimeofday (const struct timeval *, void *);
+int adjtime (const struct timeval *, struct timeval *);
+
+
+#define ITIMER_REAL    0
+#define ITIMER_VIRTUAL 1
+#define ITIMER_PROF    2
+
+struct itimerval
+{
+       struct timeval it_interval;
+       struct timeval it_value;
+};
+
+int getitimer (int, struct itimerval *);
+int setitimer (int, const struct itimerval *, struct itimerval *);
+int utimes (const char *, const struct timeval [2]);
+
+#ifdef _GNU_SOURCE
+struct timezone {
+       int tz_minuteswest;
+       int tz_dsttime;
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/times.h b/include/sys/times.h
new file mode 100644 (file)
index 0000000..aca743d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef        _SYS_TIMES_H
+#define        _SYS_TIMES_H
+
+#define __NEED_clock_t
+#include <bits/alltypes.h>
+
+struct tms
+{
+       clock_t tms_utime;
+       clock_t tms_stime;
+       clock_t tms_cutime;
+       clock_t tms_cstime;
+};
+
+clock_t times (struct tms *);
+
+#endif
diff --git a/include/sys/types.h b/include/sys/types.h
new file mode 100644 (file)
index 0000000..8be19e6
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef        _SYS_TYPES_H
+#define        _SYS_TYPES_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_loff_t
+#define __NEED_ino_t
+#define __NEED_dev_t
+#define __NEED_uid_t
+#define __NEED_gid_t
+#define __NEED_mode_t
+#define __NEED_nlink_t
+#define __NEED_off_t
+#define __NEED_pid_t
+#define __NEED_size_t
+#define __NEED_ssize_t
+#define __NEED_time_t
+#define __NEED_timer_t
+#define __NEED_clockid_t
+
+#define __NEED_int8_t
+#define __NEED_int16_t
+#define __NEED_int32_t
+#define __NEED_int64_t
+
+#define __NEED_u_int8_t
+#define __NEED_u_int16_t
+#define __NEED_u_int32_t
+#define __NEED_u_int64_t
+
+#define __NEED_register_t
+
+#define __NEED_blkcnt_t
+#define __NEED_fsblkcnt_t
+#define __NEED_fsfilcnt_t
+
+#define __NEED_id_t
+#define __NEED_key_t
+#define __NEED_clock_t
+#define __NEED_useconds_t
+#define __NEED_suseconds_t
+#define __NEED_blksize_t
+
+#include <bits/alltypes.h>
+
+#ifdef _GNU_SOURCE
+typedef unsigned long caddr_t;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/include/sys/ucontext.h b/include/sys/ucontext.h
new file mode 100644 (file)
index 0000000..5fdbd63
--- /dev/null
@@ -0,0 +1 @@
+#include <ucontext.h>
diff --git a/include/sys/uio.h b/include/sys/uio.h
new file mode 100644 (file)
index 0000000..7b068c0
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _SYS_UIO_H
+#define _SYS_UIO_H
+
+#define __NEED_size_t
+#define __NEED_ssize_t
+
+#include <bits/alltypes.h>
+
+#include <bits/uio.h>
+
+ssize_t readv (int, const struct iovec *, int);
+ssize_t writev (int, const struct iovec *, int);
+
+#endif
diff --git a/include/sys/un.h b/include/sys/un.h
new file mode 100644 (file)
index 0000000..769dac6
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef        _SYS_UN_H
+#define        _SYS_UN_H
+
+#define __NEED_sa_family_t
+#include <bits/alltypes.h>
+
+struct sockaddr_un
+{
+       sa_family_t sun_family;
+       char sun_path[108];
+};
+
+#endif
diff --git a/include/sys/user.h b/include/sys/user.h
new file mode 100644 (file)
index 0000000..24ac940
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _SYS_USER_H
+#define _SYS_USER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <limits.h>
+#include <unistd.h>
+
+#include <bits/user.h>
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sys/utsname.h b/include/sys/utsname.h
new file mode 100644 (file)
index 0000000..383e825
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef        _SYS_UTSNAME_H
+#define        _SYS_UTSNAME_H
+
+struct utsname
+{
+       char sysname[65];
+       char nodename[65];
+       char release[65];
+       char version[65];
+       char machine[65];
+#ifdef _GNU_SOURCE
+       char domainname[65];
+#else
+       char __domainname[65];
+#endif
+};
+
+int uname (struct utsname *);
+
+
+#endif
diff --git a/include/sys/vfs.h b/include/sys/vfs.h
new file mode 100644 (file)
index 0000000..a899db2
--- /dev/null
@@ -0,0 +1 @@
+#include <sys/statfs.h>
diff --git a/include/sys/vt.h b/include/sys/vt.h
new file mode 100644 (file)
index 0000000..834abfb
--- /dev/null
@@ -0,0 +1 @@
+#include <linux/vt.h>
diff --git a/include/sys/wait.h b/include/sys/wait.h
new file mode 100644 (file)
index 0000000..a185153
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef        _SYS_WAIT_H
+#define        _SYS_WAIT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_pid_t
+#define __NEED_id_t
+#define __NEED_time_t
+#define __NEED_struct_timeval
+#define __NEED_siginfo_t
+#include <bits/alltypes.h>
+
+typedef int idtype_t;
+
+pid_t wait (int *);
+int waitid (idtype_t, id_t, siginfo_t *, int);
+pid_t waitpid (pid_t, int *, int );
+//pid_t wait3 (int *, int, struct rusage *);
+//pid_t wait4 (pid_t, int *, int, struct rusage *);
+
+#include <bits/wait.h>
+#include <bits/wexitstatus.h>
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/syslog.h b/include/syslog.h
new file mode 100644 (file)
index 0000000..119c9bc
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _SYS_SYSLOG_H
+#define _SYS_SYSLOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOG_EMERG   0
+#define LOG_ALERT   1
+#define LOG_CRIT    2
+#define LOG_ERR     3
+#define LOG_WARNING 4
+#define LOG_NOTICE  5
+#define LOG_INFO    6
+#define LOG_DEBUG   7
+
+#define LOG_MASK(p) (1<<(p))
+
+#define LOG_KERN     (0<<3)
+#define LOG_USER     (1<<3)
+#define LOG_MAIL     (2<<3)
+#define LOG_DAEMON   (3<<3)
+#define LOG_AUTH     (4<<3)
+#define LOG_SYSLOG   (5<<3)
+#define LOG_LPR      (6<<3)
+#define LOG_NEWS     (7<<3)
+#define LOG_UUCP     (8<<3)
+#define LOG_CRON     (9<<3)
+
+#define LOG_LOCAL0   (16<<3)
+#define LOG_LOCAL1   (17<<3)
+#define LOG_LOCAL2   (18<<3)
+#define LOG_LOCAL3   (19<<3)
+#define LOG_LOCAL4   (20<<3)
+#define LOG_LOCAL5   (21<<3)
+#define LOG_LOCAL6   (22<<3)
+#define LOG_LOCAL7   (23<<3)
+
+#define LOG_PID    0x01
+#define LOG_CONS   0x02
+#define LOG_ODELAY 0x04
+#define LOG_NDELAY 0x08
+#define LOG_NOWAIT 0x10
+
+void closelog (void);
+void openlog (const char *, int, int);
+int setlogmask (int);
+void syslog (int, const char *, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/tar.h b/include/tar.h
new file mode 100644 (file)
index 0000000..be58984
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef        _TAR_H
+#define        _TAR_H
+
+#define TSUID   04000
+#define TSGID   02000
+#define TSVTX   01000
+#define TUREAD  00400
+#define TUWRITE 00200
+#define TUEXEC  00100
+#define TGREAD  00040
+#define TGWRITE 00020
+#define TGEXEC  00010
+#define TOREAD  00004
+#define TOWRITE 00002
+#define TOEXEC  00001
+
+#define REGTYPE  '0'
+#define AREGTYPE '\0'
+#define LNKTYPE  '1'
+#define SYMTYPE  '2'
+#define CHRTYPE  '3'
+#define BLKTYPE  '4'
+#define DIRTYPE  '5'
+#define FIFOTYPE '6'
+#define CONTTYPE '7'
+
+#define TMAGIC "ustar"
+#define TMAGLEN 6
+
+#define TVERSION "00"
+#define TVERSLEN 2
+
+#endif
diff --git a/include/termios.h b/include/termios.h
new file mode 100644 (file)
index 0000000..4c46562
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef        _TERMIOS_H
+#define        _TERMIOS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_pid_t
+
+#include <bits/alltypes.h>
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 32
+
+#include <bits/termios.h>
+
+speed_t cfgetospeed (const struct termios *);
+speed_t cfgetispeed (const struct termios *);
+int cfsetospeed (struct termios *, speed_t);
+int cfsetispeed (struct termios *, speed_t);
+
+int tcgetattr (int, struct termios *);
+int tcsetattr (int, int, const struct termios *);
+
+int tcsendbreak (int, int);
+int tcdrain (int);
+int tcflush (int, int);
+int tcflow (int, int);
+
+pid_t tcgetsid (int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/time.h b/include/time.h
new file mode 100644 (file)
index 0000000..e6cfb73
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef        _TIME_H
+#define _TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+
+#define __NEED_time_t
+#define __NEED_struct_timespec
+#define __NEED_clock_t
+#define __NEED_clockid_t
+#define __NEED_timer_t
+#define __NEED_size_t
+#define __NEED_pid_t
+
+#include <bits/alltypes.h>
+
+
+struct tm
+{
+       int tm_sec;
+       int tm_min;
+       int tm_hour;
+       int tm_mday;
+       int tm_mon;
+       int tm_year;
+       int tm_wday;
+       int tm_yday;
+       int tm_isdst;
+       long __tm_gmtoff;
+       const char *__tm_zone;
+};
+
+struct itimerspec
+{
+       struct timespec it_interval;
+       struct timespec it_value;
+};
+
+#define CLOCKS_PER_SEC 1000000UL
+
+#define CLOCK_REALTIME           0
+#define CLOCK_MONOTONIC          1
+#define CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOCK_THREAD_CPUTIME_ID  3
+
+#define TIMER_ABSTIME 1
+
+
+
+clock_t clock (void);
+time_t time (time_t *);
+double difftime (time_t, time_t);
+time_t mktime (struct tm *);
+size_t strftime (char *, size_t, const char *, const struct tm *);
+char *strptime (const char *, const char *, struct tm *);
+
+struct tm *gmtime (const time_t *);
+struct tm *gmtime_r (const time_t *, struct tm *);
+struct tm *localtime (const time_t *);
+struct tm *localtime_r (const time_t *, struct tm *);
+
+char *asctime (const struct tm *);
+char *asctime_r (const struct tm *, char *);
+char *ctime (const time_t *);
+char *ctime_r (const time_t *, char *);
+
+
+extern int daylight;
+extern long timezone;
+extern char *tzname[2];
+
+void tzset (void);
+
+
+
+int nanosleep (const struct timespec *, struct timespec *);
+
+
+int clock_getres (clockid_t, struct timespec *);
+int clock_gettime (clockid_t, struct timespec *);
+int clock_settime (clockid_t, const struct timespec *);
+
+int clock_nanosleep (clockid_t, int, const struct timespec *, struct timespec *);
+int clock_getcpuclockid (pid_t, clockid_t *);
+
+/* FIXME */
+struct sigevent;
+int timer_create (clockid_t, struct sigevent *, timer_t *);
+int timer_delete (timer_t);
+
+int timer_settime (timer_t, int, const struct itimerspec *, struct itimerspec *);
+int timer_gettime (timer_t, struct itimerspec *);
+int timer_getoverrun (timer_t);
+
+
+extern int getdate_err;
+extern struct tm *getdate (const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/include/ucontext.h b/include/ucontext.h
new file mode 100644 (file)
index 0000000..db33567
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _UCONTEXT_H
+#define _UCONTEXT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <signal.h>
+
+struct __fpstate {
+       unsigned long __x[7];
+       unsigned char __y[80];
+       unsigned long __z;
+};
+
+typedef struct {
+       unsigned long __gregs[19];
+       void *__fpregs;
+       unsigned long __oldmask, __cr2;
+} mcontext_t;
+
+typedef struct __ucontext {
+       unsigned long uc_flags;
+       struct __ucontext *uc_link;
+       stack_t uc_stack;
+       mcontext_t uc_mcontext;
+       sigset_t uc_sigmask;
+       struct __fpstate __fpregs_mem;
+} ucontext_t;
+
+int  getcontext(ucontext_t *);
+void makecontext(ucontext_t *, void (*)(void), int, ...);
+int  setcontext(const ucontext_t *);
+int  swapcontext(ucontext_t *, const ucontext_t *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/ulimit.h b/include/ulimit.h
new file mode 100644 (file)
index 0000000..efdcd31
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _ULIMIT_H
+#define _ULIMIT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UL_GETFSIZE 1
+#define UL_SETFSIZE 2
+
+long ulimit (int, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/unistd.h b/include/unistd.h
new file mode 100644 (file)
index 0000000..5ad0704
--- /dev/null
@@ -0,0 +1,464 @@
+#ifndef        _UNISTD_H
+#define        _UNISTD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define STDIN_FILENO  0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+#undef SEEK_SET
+#undef SEEK_CUR
+#undef SEEK_END
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void*)0)
+#endif
+
+#define __NEED_size_t
+#define __NEED_ssize_t
+#define __NEED_uid_t
+#define __NEED_gid_t
+#define __NEED_off_t
+#define __NEED_pid_t
+#define __NEED_useconds_t
+#define __NEED_intptr_t
+
+#include <bits/alltypes.h>
+
+int pipe(int [2]);
+int close(int);
+int dup(int);
+int dup2(int, int);
+off_t lseek(int, off_t, int);
+int fsync(int);
+void sync(void);
+int fdatasync(int);
+
+ssize_t read(int, void *, size_t);
+ssize_t write(int, const void *, size_t);
+ssize_t pread(int, void *, size_t, off_t);
+ssize_t pwrite(int, const void *, size_t, off_t);
+
+#define F_ULOCK 0
+#define F_LOCK  1
+#define F_TLOCK 2
+#define F_TEST  3
+int lockf(int, int, off_t);
+
+int chown(const char *, uid_t, gid_t);
+int fchown(int, uid_t, gid_t);
+int lchown(const char *, uid_t, gid_t);
+int fchownat(int, const char *, uid_t, gid_t, int);
+
+int link(const char *, const char *);
+int linkat(int, const char *, int, const char *, int);
+int symlink(const char *, const char *);
+int symlinkat(const char *, int, const char *);
+int readlink(const char *, char *, size_t);
+int readlinkat(int, const char *, char *, size_t);
+int unlink(const char *);
+int unlinkat(int, const char *, int);
+int rmdir(const char *);
+int truncate(const char *, off_t);
+int ftruncate(int, off_t);
+
+#define F_OK 0
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+int access(const char *, int);
+int faccessat(int, const char *, int, int);
+
+int chdir(const char *);
+int fchdir(int);
+char *getcwd(char *, size_t);
+int chroot(const char *); /* dropped */
+
+unsigned alarm(unsigned);
+useconds_t ualarm(useconds_t, useconds_t);
+unsigned sleep(unsigned);
+int usleep(useconds_t);
+int pause(void);
+int nice(int);
+
+pid_t fork(void);
+pid_t vfork(void);
+int execve(const char *, char *const [], char *const []);
+int execv(const char *, char *const []);
+int execle(const char *, ...);
+int execl(const char *, ...);
+int execvp(const char *, char *const []);
+int execlp(const char *, ...);
+void _exit(int);
+
+pid_t getpid(void);
+pid_t getppid(void);
+pid_t getpgrp(void);
+pid_t getpgid(pid_t);
+int setpgid(pid_t, pid_t);
+int setpgrp(void);
+pid_t setsid(void);
+pid_t getsid(pid_t);
+char *ttyname(int);
+int ttyname_r(int, char *, size_t);
+int isatty(int);
+pid_t tcgetpgrp(int);
+int tcsetpgrp(int, pid_t);
+
+uid_t getuid(void);
+uid_t geteuid(void);
+gid_t getgid(void);
+gid_t getegid(void);
+int getgroups(int, gid_t []);
+int setuid(uid_t);
+int setreuid(uid_t, uid_t);
+int seteuid(uid_t);
+int setgid(gid_t);
+int setregid(gid_t, gid_t);
+int setegid(gid_t);
+
+char *getlogin(void);
+int getlogin_r(char *, size_t);
+long gethostid(void);
+int gethostname(char *, size_t);
+int sethostname(const char *, size_t);
+int getpagesize(void);
+char *ctermid(char *);
+
+int vhangup(void); /* dropped */
+
+int getopt(int, char * const [], const char *);
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+char *crypt(const char *, const char *);
+void encrypt(char *, int);
+
+void swab(const void *, void *, ssize_t);
+
+long pathconf(const char *, int);
+long fpathconf(int, int);
+long sysconf(int);
+size_t confstr(int, char *, size_t);
+
+#define _XOPEN_VERSION          700
+#define _XOPEN_UNIX             1
+#define _XOPEN_ENH_I18N         1
+
+#define _POSIX_VERSION          200809L
+#define _POSIX2_VERSION         _POSIX_VERSION
+
+#define _POSIX_CHOWN_RESTRICTED 1
+#define _POSIX_IPV6             _POSIX_VERSION
+#define _POSIX_JOB_CONTROL      1
+#define _POSIX_MAPPED_FILES     _POSIX_VERSION
+#define _POSIX_MEMLOCK          _POSIX_VERSION
+#define _POSIX_MEMLOCK_RANGE    _POSIX_VERSION
+#define _POSIX_MEMORY_PROTECTION _POSIX_VERSION
+#define _POSIX_NO_TRUNC         1
+#define _POSIX_RAW_SOCKETS      _POSIX_VERSION
+#define _POSIX_REALTIME_SIGNALS _POSIX_VERSION
+#define _POSIX_REGEXP           1
+#define _POSIX_SAVED_IDS        1
+#define _POSIX_SHELL            1
+#define _POSIX_VDISABLE         0
+
+#define _POSIX_THREADS          _POSIX_VERSION
+#define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION
+#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
+#define _POSIX_TIMERS           _POSIX_VERSION
+#define _POSIX_TIMEOUTS         _POSIX_VERSION
+#define _POSIX_MONOTONIC_CLOCK  _POSIX_VERSION
+#define _POSIX_CPUTIME          _POSIX_VERSION
+#define _POSIX_CLOCK_SELECTION  _POSIX_VERSION
+#define _POSIX_BARRIERS         _POSIX_VERSION
+#define _POSIX_SPIN_LOCKS       _POSIX_VERSION
+#define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION
+#define _POSIX_ASYNCHRONOUS_IO  _POSIX_VERSION
+#define _POSIX_SEMAPHORES       _POSIX_VERSION
+
+#define _POSIX2_C_BIND          _POSIX_VERSION
+
+#include <bits/posix.h>
+
+
+
+#define _PC_LINK_MAX   0
+#define _PC_MAX_CANON  1
+#define _PC_MAX_INPUT  2
+#define _PC_NAME_MAX   3
+#define _PC_PATH_MAX   4
+#define _PC_PIPE_BUF   5
+#define _PC_CHOWN_RESTRICTED   6
+#define _PC_NO_TRUNC   7
+#define _PC_VDISABLE   8
+#define _PC_SYNC_IO    9
+#define _PC_ASYNC_IO   10
+#define _PC_PRIO_IO    11
+#define _PC_SOCK_MAXBUF        12
+#define _PC_FILESIZEBITS       13
+#define _PC_REC_INCR_XFER_SIZE 14
+#define _PC_REC_MAX_XFER_SIZE  15
+#define _PC_REC_MIN_XFER_SIZE  16
+#define _PC_REC_XFER_ALIGN     17
+#define _PC_ALLOC_SIZE_MIN     18
+#define _PC_SYMLINK_MAX        19
+#define _PC_2_SYMLINKS 20
+
+#define _SC_ARG_MAX    0
+#define _SC_CHILD_MAX  1
+#define _SC_CLK_TCK    2
+#define _SC_NGROUPS_MAX        3
+#define _SC_OPEN_MAX   4
+#define _SC_STREAM_MAX 5
+#define _SC_TZNAME_MAX 6
+#define _SC_JOB_CONTROL        7
+#define _SC_SAVED_IDS  8
+#define _SC_REALTIME_SIGNALS   9
+#define _SC_PRIORITY_SCHEDULING        10
+#define _SC_TIMERS     11
+#define _SC_ASYNCHRONOUS_IO    12
+#define _SC_PRIORITIZED_IO     13
+#define _SC_SYNCHRONIZED_IO    14
+#define _SC_FSYNC      15
+#define _SC_MAPPED_FILES       16
+#define _SC_MEMLOCK    17
+#define _SC_MEMLOCK_RANGE      18
+#define _SC_MEMORY_PROTECTION  19
+#define _SC_MESSAGE_PASSING    20
+#define _SC_SEMAPHORES 21
+#define _SC_SHARED_MEMORY_OBJECTS      22
+#define _SC_AIO_LISTIO_MAX     23
+#define _SC_AIO_MAX    24
+#define _SC_AIO_PRIO_DELTA_MAX 25
+#define _SC_DELAYTIMER_MAX     26
+#define _SC_MQ_OPEN_MAX        27
+#define _SC_MQ_PRIO_MAX        28
+#define _SC_VERSION    29
+#define _SC_PAGE_SIZE  30
+#define _SC_PAGESIZE   30 /* !! */
+#define _SC_RTSIG_MAX  31
+#define _SC_SEM_NSEMS_MAX      32
+#define _SC_SEM_VALUE_MAX      33
+#define _SC_SIGQUEUE_MAX       34
+#define _SC_TIMER_MAX  35
+#define _SC_BC_BASE_MAX        36
+#define _SC_BC_DIM_MAX 37
+#define _SC_BC_SCALE_MAX       38
+#define _SC_BC_STRING_MAX      39
+#define _SC_COLL_WEIGHTS_MAX   40
+#define _SC_EQUIV_CLASS_MAX    41
+#define _SC_EXPR_NEST_MAX      42
+#define _SC_LINE_MAX   43
+#define _SC_RE_DUP_MAX 44
+#define _SC_CHARCLASS_NAME_MAX 45
+#define _SC_2_VERSION  46
+#define _SC_2_C_BIND   47
+#define _SC_2_C_DEV    48
+#define _SC_2_FORT_DEV 49
+#define _SC_2_FORT_RUN 50
+#define _SC_2_SW_DEV   51
+#define _SC_2_LOCALEDEF        52
+#define _SC_PII        53
+#define _SC_PII_XTI    54
+#define _SC_PII_SOCKET 55
+#define _SC_PII_INTERNET       56
+#define _SC_PII_OSI    57
+#define _SC_POLL       58
+#define _SC_SELECT     59
+#define _SC_UIO_MAXIOV 60 /* !! */
+#define _SC_IOV_MAX    60
+#define _SC_PII_INTERNET_STREAM        61
+#define _SC_PII_INTERNET_DGRAM 62
+#define _SC_PII_OSI_COTS       63
+#define _SC_PII_OSI_CLTS       64
+#define _SC_PII_OSI_M  65
+#define _SC_T_IOV_MAX  66
+#define _SC_THREADS    67
+#define _SC_THREAD_SAFE_FUNCTIONS      68
+#define _SC_GETGR_R_SIZE_MAX   69
+#define _SC_GETPW_R_SIZE_MAX   70
+#define _SC_LOGIN_NAME_MAX     71
+#define _SC_TTY_NAME_MAX       72
+#define _SC_THREAD_DESTRUCTOR_ITERATIONS       73
+#define _SC_THREAD_KEYS_MAX    74
+#define _SC_THREAD_STACK_MIN   75
+#define _SC_THREAD_THREADS_MAX 76
+#define _SC_THREAD_ATTR_STACKADDR      77
+#define _SC_THREAD_ATTR_STACKSIZE      78
+#define _SC_THREAD_PRIORITY_SCHEDULING 79
+#define _SC_THREAD_PRIO_INHERIT        80
+#define _SC_THREAD_PRIO_PROTECT        81
+#define _SC_THREAD_PROCESS_SHARED      82
+#define _SC_NPROCESSORS_CONF   83
+#define _SC_NPROCESSORS_ONLN   84
+#define _SC_PHYS_PAGES 85
+#define _SC_AVPHYS_PAGES       86
+#define _SC_ATEXIT_MAX 87
+#define _SC_PASS_MAX   88
+#define _SC_XOPEN_VERSION      89
+#define _SC_XOPEN_XCU_VERSION  90
+#define _SC_XOPEN_UNIX 91
+#define _SC_XOPEN_CRYPT        92
+#define _SC_XOPEN_ENH_I18N     93
+#define _SC_XOPEN_SHM  94
+#define _SC_2_CHAR_TERM        95
+#define _SC_2_C_VERSION        96
+#define _SC_2_UPE      97
+#define _SC_XOPEN_XPG2 98
+#define _SC_XOPEN_XPG3 99
+#define _SC_XOPEN_XPG4 100
+#define _SC_CHAR_BIT   101
+#define _SC_CHAR_MAX   102
+#define _SC_CHAR_MIN   103
+#define _SC_INT_MAX    104
+#define _SC_INT_MIN    105
+#define _SC_LONG_BIT   106
+#define _SC_WORD_BIT   107
+#define _SC_MB_LEN_MAX 108
+#define _SC_NZERO      109
+#define _SC_SSIZE_MAX  110
+#define _SC_SCHAR_MAX  111
+#define _SC_SCHAR_MIN  112
+#define _SC_SHRT_MAX   113
+#define _SC_SHRT_MIN   114
+#define _SC_UCHAR_MAX  115
+#define _SC_UINT_MAX   116
+#define _SC_ULONG_MAX  117
+#define _SC_USHRT_MAX  118
+#define _SC_NL_ARGMAX  119
+#define _SC_NL_LANGMAX 120
+#define _SC_NL_MSGMAX  121
+#define _SC_NL_NMAX    122
+#define _SC_NL_SETMAX  123
+#define _SC_NL_TEXTMAX 124
+#define _SC_XBS5_ILP32_OFF32   125
+#define _SC_XBS5_ILP32_OFFBIG  126
+#define _SC_XBS5_LP64_OFF64    127
+#define _SC_XBS5_LPBIG_OFFBIG  128
+#define _SC_XOPEN_LEGACY       129
+#define _SC_XOPEN_REALTIME     130
+#define _SC_XOPEN_REALTIME_THREADS     131
+#define _SC_ADVISORY_INFO      132
+#define _SC_BARRIERS   133
+#define _SC_BASE       134
+#define _SC_C_LANG_SUPPORT     135
+#define _SC_C_LANG_SUPPORT_R   136
+#define _SC_CLOCK_SELECTION    137
+#define _SC_CPUTIME    138
+#define _SC_THREAD_CPUTIME     139
+#define _SC_DEVICE_IO  140
+#define _SC_DEVICE_SPECIFIC    141
+#define _SC_DEVICE_SPECIFIC_R  142
+#define _SC_FD_MGMT    143
+#define _SC_FIFO       144
+#define _SC_PIPE       145
+#define _SC_FILE_ATTRIBUTES    146
+#define _SC_FILE_LOCKING       147
+#define _SC_FILE_SYSTEM        148
+#define _SC_MONOTONIC_CLOCK    149
+#define _SC_MULTI_PROCESS      150
+#define _SC_SINGLE_PROCESS     151
+#define _SC_NETWORKING 152
+#define _SC_READER_WRITER_LOCKS        153
+#define _SC_SPIN_LOCKS 154
+#define _SC_REGEXP     155
+#define _SC_REGEX_VERSION      156
+#define _SC_SHELL      157
+#define _SC_SIGNALS    158
+#define _SC_SPAWN      159
+#define _SC_SPORADIC_SERVER    160
+#define _SC_THREAD_SPORADIC_SERVER     161
+#define _SC_SYSTEM_DATABASE    162
+#define _SC_SYSTEM_DATABASE_R  163
+#define _SC_TIMEOUTS   164
+#define _SC_TYPED_MEMORY_OBJECTS       165
+#define _SC_USER_GROUPS        166
+#define _SC_USER_GROUPS_R      167
+#define _SC_2_PBS      168
+#define _SC_2_PBS_ACCOUNTING   169
+#define _SC_2_PBS_LOCATE       170
+#define _SC_2_PBS_MESSAGE      171
+#define _SC_2_PBS_TRACK        172
+#define _SC_SYMLOOP_MAX        173
+#define _SC_STREAMS    174
+#define _SC_2_PBS_CHECKPOINT   175
+#define _SC_V6_ILP32_OFF32     176
+#define _SC_V6_ILP32_OFFBIG    177
+#define _SC_V6_LP64_OFF64      178
+#define _SC_V6_LPBIG_OFFBIG    179
+#define _SC_HOST_NAME_MAX      180
+#define _SC_TRACE      181
+#define _SC_TRACE_EVENT_FILTER 182
+#define _SC_TRACE_INHERIT      183
+#define _SC_TRACE_LOG  184
+
+#define _SC_IPV6       235
+#define _SC_RAW_SOCKETS        236
+#define _SC_V7_ILP32_OFF32     237
+#define _SC_V7_ILP32_OFFBIG    238
+#define _SC_V7_LP64_OFF64      239
+#define _SC_V7_LPBIG_OFFBIG    240
+#define _SC_SS_REPL_MAX        241
+#define _SC_TRACE_EVENT_NAME_MAX       242
+#define _SC_TRACE_NAME_MAX     243
+#define _SC_TRACE_SYS_MAX      244
+#define _SC_TRACE_USER_EVENT_MAX       245
+#define _SC_XOPEN_STREAMS      246
+#define _SC_THREAD_ROBUST_PRIO_INHERIT 247
+#define _SC_THREAD_ROBUST_PRIO_PROTECT 248
+
+#define _CS_PATH       0
+#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS     1
+#define _CS_GNU_LIBC_VERSION   2
+#define _CS_GNU_LIBPTHREAD_VERSION     3
+#define _CS_POSIX_V5_WIDTH_RESTRICTED_ENVS     4
+#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS     5
+
+#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS        1116
+#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS       1117
+#define _CS_POSIX_V6_ILP32_OFF32_LIBS  1118
+#define _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS     1119
+#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS       1120
+#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS      1121
+#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS 1122
+#define _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS    1123
+#define _CS_POSIX_V6_LP64_OFF64_CFLAGS 1124
+#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS        1125
+#define _CS_POSIX_V6_LP64_OFF64_LIBS   1126
+#define _CS_POSIX_V6_LP64_OFF64_LINTFLAGS      1127
+#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS       1128
+#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS      1129
+#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS 1130
+#define _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS    1131
+#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS        1132
+#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS       1133
+#define _CS_POSIX_V7_ILP32_OFF32_LIBS  1134
+#define _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS     1135
+#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS       1136
+#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS      1137
+#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS 1138
+#define _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS    1139
+#define _CS_POSIX_V7_LP64_OFF64_CFLAGS 1140
+#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS        1141
+#define _CS_POSIX_V7_LP64_OFF64_LIBS   1142
+#define _CS_POSIX_V7_LP64_OFF64_LINTFLAGS      1143
+#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS       1144
+#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS      1145
+#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS 1146
+#define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS    1147
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/utime.h b/include/utime.h
new file mode 100644 (file)
index 0000000..ec82e0f
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef        _UTIME_H
+#define        _UTIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_time_t
+
+#include <bits/alltypes.h>
+
+struct utimbuf
+{
+       time_t actime;
+       time_t modtime;
+};
+
+int utime (const char *, const struct utimbuf *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/utmp.h b/include/utmp.h
new file mode 100644 (file)
index 0000000..f60ff88
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _UTMP_H
+#define _UTMP_H
+
+#include <utmpx.h>
+
+#define ut_time ut_tv.tv_sec
+#define ut_name ut_user
+#define ut_exit __ut_exit
+#define e_termination __e_termination
+#define e_exit __e_exit
+#define utmp utmpx
+#define endutent endutxent
+#define getutent getutxent
+#define setutent setutxent
+#define getutid getutxid
+#define getutline getutxline
+#define pututline pututxline
+#define utmpname(x) (-1)
+
+#define _PATH_UTMP "/dev/null"
+#define _PATH_WTMP "/dev/null"
+
+#endif
diff --git a/include/utmpx.h b/include/utmpx.h
new file mode 100644 (file)
index 0000000..9a2e307
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _UTMPX_H
+#define _UTMPX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_pid_t
+#define __NEED_time_t
+#define __NEED_struct_timeval
+
+#include <bits/alltypes.h>
+
+struct utmpx
+{
+       short ut_type;
+       pid_t ut_pid;
+       char ut_line[32];
+       char ut_id[4];
+       char ut_user[32];
+       char ut_host[256];
+       struct {
+               short __e_termination;
+               short __e_exit;
+       } __ut_exit;
+       long ut_session;
+       struct timeval ut_tv;
+       unsigned ut_addr_v6[4];
+       char __unused[20];
+};
+
+void          endutxent(void);
+struct utmpx *getutxent(void);
+struct utmpx *getutxid(const struct utmpx *);
+struct utmpx *getutxline(const struct utmpx *);
+struct utmpx *pututxline(const struct utmpx *);
+void          setutxent(void);
+
+#define EMPTY           0
+#define BOOT_TIME       2
+#define NEW_TIME        3
+#define OLD_TIME        4
+#define INIT_PROCESS    5
+#define LOGIN_PROCESS   6
+#define USER_PROCESS    7
+#define DEAD_PROCESS    8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/wchar.h b/include/wchar.h
new file mode 100644 (file)
index 0000000..3f325bf
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef _WCHAR_H
+#define _WCHAR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_FILE
+#define __NEED_va_list
+#define __NEED_size_t
+#define __NEED_wchar_t
+#define __NEED_wint_t
+#define __NEED_wctype_t
+
+#include <bits/alltypes.h>
+
+#undef NULL
+#define NULL ((void*)0)
+
+#undef WCHAR_MIN
+#undef WCHAR_MAX
+#define WCHAR_MIN (-1-0x7fffffff)
+#define WCHAR_MAX (0x7fffffff)
+
+#undef WEOF
+#define WEOF (-1)
+
+
+typedef struct
+{
+       unsigned __opaque1, __opaque2;
+} mbstate_t;
+
+wchar_t *wcscpy (wchar_t *, const wchar_t *);
+wchar_t *wcsncpy (wchar_t *, const wchar_t *, size_t);
+
+wchar_t *wcscat (wchar_t *, const wchar_t *);
+wchar_t *wcsncat (wchar_t *, const wchar_t *, size_t);
+
+int wcscmp (const wchar_t *, const wchar_t *);
+int wcsncmp (const wchar_t *, const wchar_t *, size_t);
+
+size_t wcsxfrm (wchar_t *, const wchar_t *, size_t n);
+
+wchar_t *wcschr (const wchar_t *, wchar_t);
+wchar_t *wcsrchr (const wchar_t *, wchar_t);
+
+size_t wcscspn (const wchar_t *, const wchar_t *);
+size_t wcsspn (const wchar_t *, const wchar_t *);
+wchar_t *wcspbrk (const wchar_t *, const wchar_t *);
+
+wchar_t *wcstok (wchar_t *, const wchar_t *, wchar_t **);
+
+size_t wcslen (const wchar_t *);
+
+wchar_t *wcsstr (const wchar_t *, const wchar_t *);
+wchar_t *wcswcs (const wchar_t *, const wchar_t *);
+
+wchar_t *wmemchr (const wchar_t *, wchar_t, size_t);
+int wmemcmp (const wchar_t *, const wchar_t *, size_t);
+wchar_t *wmemcpy (wchar_t *, const wchar_t *, size_t);
+wchar_t *wmemmove (wchar_t *, const wchar_t *, size_t);
+wchar_t *wmemset (wchar_t *, wchar_t, size_t);
+
+wint_t btowc (int);
+int wctob (wint_t);
+
+int mbsinit (const mbstate_t *);
+size_t mbrtowc (wchar_t *, const char *, size_t, mbstate_t *);
+size_t wcrtomb (char *, wchar_t, mbstate_t *);
+
+size_t mbrlen (const char *, size_t, mbstate_t *);
+
+size_t mbsrtowcs (wchar_t *, const char **, size_t, mbstate_t *);
+size_t wcsrtombs (char *, const wchar_t **, size_t, mbstate_t *);
+
+int wcwidth (wchar_t);
+int wcswidth (const wchar_t *, size_t);
+
+float wcstof (const wchar_t *, wchar_t **);
+double wcstod (const wchar_t *, wchar_t **);
+long double wcstold (const wchar_t *, wchar_t **);
+
+long wcstol (const wchar_t *, wchar_t **, int);
+unsigned long wcstoul (const wchar_t *, wchar_t **, int);
+
+long long wcstoll (const wchar_t *, wchar_t **, int);
+unsigned long long wcstoull (const wchar_t *, wchar_t **, int);
+
+
+
+int fwide (FILE *, int);
+
+
+int wprintf (const wchar_t *, ...);
+int fwprintf (FILE *, const wchar_t *, ...);
+int swprintf (wchar_t *, const wchar_t *, ...);
+
+int vwprintf (const wchar_t *, va_list);
+int vfwprintf (FILE *, const wchar_t *, va_list);
+int vswprintf (wchar_t *, const wchar_t *, va_list);
+
+int wscanf (const wchar_t *, ...);
+int fwscanf (FILE *, const wchar_t *, ...);
+int swscanf (const wchar_t *, const wchar_t *, ...);
+
+int vwscanf (const wchar_t *, va_list);
+int vfwscanf (FILE *, const wchar_t *, va_list);
+int vswscanf (const wchar_t *, const wchar_t *, va_list);
+
+wint_t fgetwc (FILE *);
+wint_t getwc (FILE *);
+wint_t getwchar (void);
+
+wint_t fputwc (wchar_t, FILE *);
+wint_t putwc (wchar_t, FILE *);
+wint_t putwchar (wchar_t);
+
+wchar_t *fgetws (wchar_t *, int, FILE *);
+int fputws (const wchar_t *, FILE *);
+
+wint_t ungetwc (wint_t, FILE *);
+
+struct tm;
+size_t wcsftime (wchar_t *, size_t, const wchar_t *, const struct tm *);
+
+#undef iswdigit
+
+int       iswalnum(wint_t);
+int       iswalpha(wint_t);
+int       iswblank(wint_t);
+int       iswcntrl(wint_t);
+int       iswdigit(wint_t);
+int       iswgraph(wint_t);
+int       iswlower(wint_t);
+int       iswprint(wint_t);
+int       iswpunct(wint_t);
+int       iswspace(wint_t);
+int       iswupper(wint_t);
+int       iswxdigit(wint_t);
+int       iswctype(wint_t, wctype_t);
+wint_t    towlower(wint_t);
+wint_t    towupper(wint_t);
+wctype_t  wctype(const char *);
+
+#define iswdigit(a) ((unsigned)(a)-'0' < 10)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/wctype.h b/include/wctype.h
new file mode 100644 (file)
index 0000000..8b6c9d9
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _WCTYPE_H
+#define _WCTYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_wint_t
+#define __NEED_wctrans_t
+#define __NEED_wctype_t
+
+#include <bits/alltypes.h>
+
+#undef WEOF
+#define WEOF (-1)
+
+#undef iswdigit
+
+int       iswalnum(wint_t);
+int       iswalpha(wint_t);
+int       iswblank(wint_t);
+int       iswcntrl(wint_t);
+int       iswdigit(wint_t);
+int       iswgraph(wint_t);
+int       iswlower(wint_t);
+int       iswprint(wint_t);
+int       iswpunct(wint_t);
+int       iswspace(wint_t);
+int       iswupper(wint_t);
+int       iswxdigit(wint_t);
+int       iswctype(wint_t, wctype_t);
+wint_t    towctrans(wint_t, wctrans_t);
+wint_t    towlower(wint_t);
+wint_t    towupper(wint_t);
+wctrans_t wctrans(const char *);
+wctype_t  wctype(const char *);
+
+#define iswdigit(a) ((unsigned)((a)-L'0') < 10)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/wordexp.h b/include/wordexp.h
new file mode 100644 (file)
index 0000000..91995c4
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef        _WORDEXP_H
+#define        _WORDEXP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+#define WRDE_DOOFFS  1
+#define WRDE_APPEND  2
+#define WRDE_NOCMD   4
+#define WRDE_REUSE   8
+#define WRDE_SHOWERR 16
+#define WRDE_UNDEF   32
+
+typedef struct
+{
+       size_t we_wordc;
+       char **wc_wordv;
+       size_t we_offs;
+} wordexp_t;
+
+#define WRDE_NOSYS   -1
+#define WRDE_NOSPACE 1
+#define WRDE_BADCHAR 2
+#define WRDE_BADVAL  3
+#define WRDE_CMDSUB  4
+#define WRDE_SYNTAX  5
+
+int wordexp (const char *, wordexp_t *, int);
+void wordfree (wordexp_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/conf/fpathconf.c b/src/conf/fpathconf.c
new file mode 100644 (file)
index 0000000..af7e4d3
--- /dev/null
@@ -0,0 +1,35 @@
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+long fpathconf(int fd, int name)
+{
+       static const short values[] = {
+               [_PC_LINK_MAX] = _POSIX_LINK_MAX,
+               [_PC_MAX_CANON] = _POSIX_MAX_CANON,
+               [_PC_MAX_INPUT] = _POSIX_MAX_INPUT,
+               [_PC_NAME_MAX] = NAME_MAX,
+               [_PC_PATH_MAX] = PATH_MAX,
+               [_PC_PIPE_BUF] = PIPE_BUF,
+               [_PC_CHOWN_RESTRICTED] = 1,
+               [_PC_NO_TRUNC] = 1,
+               [_PC_VDISABLE] = 0,
+               [_PC_SYNC_IO] = 0,
+               [_PC_ASYNC_IO] = 0,
+               [_PC_PRIO_IO] = 0,
+               [_PC_SOCK_MAXBUF] = -1,
+               [_PC_FILESIZEBITS] = sizeof(off_t),
+               [_PC_REC_INCR_XFER_SIZE] = PAGE_SIZE,
+               [_PC_REC_MAX_XFER_SIZE] = PAGE_SIZE,
+               [_PC_REC_MIN_XFER_SIZE] = PAGE_SIZE,
+               [_PC_REC_XFER_ALIGN] = PAGE_SIZE,
+               [_PC_ALLOC_SIZE_MIN] = PAGE_SIZE,
+               [_PC_SYMLINK_MAX] = SYMLINK_MAX,
+               [_PC_2_SYMLINKS] = 1
+       };
+       if (name > sizeof(values)/sizeof(values[0])) {
+               errno = EINVAL;
+               return -1;
+       }
+       return values[name];
+}
diff --git a/src/conf/pathconf.c b/src/conf/pathconf.c
new file mode 100644 (file)
index 0000000..01e19c5
--- /dev/null
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+long pathconf(const char *path, int name)
+{
+       return fpathconf(-1, name);
+}
diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
new file mode 100644 (file)
index 0000000..cdaeb2a
--- /dev/null
@@ -0,0 +1,222 @@
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#define VER (-2)
+#define OFLOW (-3)
+
+long sysconf(int name)
+{
+       static const short values[] = {
+               [_SC_ARG_MAX] = OFLOW,
+               [_SC_CHILD_MAX] = -1,
+               [_SC_CLK_TCK] = 100,
+               [_SC_NGROUPS_MAX] = 32,
+               [_SC_OPEN_MAX] = 1024,
+               [_SC_STREAM_MAX] = -1,
+               [_SC_TZNAME_MAX] = TZNAME_MAX,
+               [_SC_JOB_CONTROL] = 1,
+               [_SC_SAVED_IDS] = 1,
+               [_SC_REALTIME_SIGNALS] = 1,
+               [_SC_PRIORITY_SCHEDULING] = -1,
+               [_SC_TIMERS] = VER,
+               [_SC_ASYNCHRONOUS_IO] = VER,
+               [_SC_PRIORITIZED_IO] = -1,
+               [_SC_SYNCHRONIZED_IO] = -1,
+               [_SC_FSYNC] = -1,
+               [_SC_MAPPED_FILES] = VER,
+               [_SC_MEMLOCK] = VER,
+               [_SC_MEMLOCK_RANGE] = VER,
+               [_SC_MEMORY_PROTECTION] = VER,
+               [_SC_MESSAGE_PASSING] = -1,
+               [_SC_SEMAPHORES] = VER,
+               [_SC_SHARED_MEMORY_OBJECTS] = -1,
+               [_SC_AIO_LISTIO_MAX] = -1,
+               [_SC_AIO_MAX] = -1,
+               [_SC_AIO_PRIO_DELTA_MAX] = 0, /* ?? */
+               [_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX,
+               [_SC_MQ_OPEN_MAX] = -1,
+               [_SC_MQ_PRIO_MAX] = _POSIX_MQ_PRIO_MAX,
+               [_SC_VERSION] = VER,
+               [_SC_PAGE_SIZE] = PAGE_SIZE,
+               [_SC_RTSIG_MAX] = 63, /* ?? */
+               [_SC_SEM_NSEMS_MAX] = _POSIX_SEM_NSEMS_MAX,
+               [_SC_SEM_VALUE_MAX] = _POSIX_SEM_VALUE_MAX,
+               [_SC_SIGQUEUE_MAX] = -1,
+               [_SC_TIMER_MAX] = -1,
+               [_SC_BC_BASE_MAX] = _POSIX2_BC_BASE_MAX,
+               [_SC_BC_DIM_MAX] = _POSIX2_BC_DIM_MAX,
+               [_SC_BC_SCALE_MAX] = _POSIX2_BC_SCALE_MAX,
+               [_SC_BC_STRING_MAX] = _POSIX2_BC_STRING_MAX,
+               [_SC_COLL_WEIGHTS_MAX] = COLL_WEIGHTS_MAX,
+               [_SC_EQUIV_CLASS_MAX] = -1, /* ?? */
+               [_SC_EXPR_NEST_MAX] = -1,
+               [_SC_LINE_MAX] = -1,
+               [_SC_RE_DUP_MAX] = RE_DUP_MAX,
+               [_SC_CHARCLASS_NAME_MAX] = -1, /* ?? */
+               [_SC_2_VERSION] = VER,
+               [_SC_2_C_BIND] = VER,
+               [_SC_2_C_DEV] = -1,
+               [_SC_2_FORT_DEV] = -1,
+               [_SC_2_FORT_RUN] = -1,
+               [_SC_2_SW_DEV] = -1,
+               [_SC_2_LOCALEDEF] = -1,
+               [_SC_PII] = -1, /* ????????? */
+               [_SC_PII_XTI] = -1,
+               [_SC_PII_SOCKET] = -1,
+               [_SC_PII_INTERNET] = -1,
+               [_SC_PII_OSI] = -1,
+               [_SC_POLL] = 1,
+               [_SC_SELECT] = 1,
+               [_SC_IOV_MAX] = IOV_MAX,
+               [_SC_PII_INTERNET_STREAM] = -1,
+               [_SC_PII_INTERNET_DGRAM] = -1,
+               [_SC_PII_OSI_COTS] = -1,
+               [_SC_PII_OSI_CLTS] = -1,
+               [_SC_PII_OSI_M] = -1,
+               [_SC_T_IOV_MAX] = -1,
+               [_SC_THREADS] = VER,
+               [_SC_THREAD_SAFE_FUNCTIONS] = VER,
+               [_SC_GETGR_R_SIZE_MAX] = -1,
+               [_SC_GETPW_R_SIZE_MAX] = -1,
+               [_SC_LOGIN_NAME_MAX] = 256,
+               [_SC_TTY_NAME_MAX] = TTY_NAME_MAX,
+               [_SC_THREAD_DESTRUCTOR_ITERATIONS] = _POSIX_THREAD_DESTRUCTOR_ITERATIONS,
+               [_SC_THREAD_KEYS_MAX] = -1,
+               [_SC_THREAD_STACK_MIN] = 2*PAGE_SIZE,
+               [_SC_THREAD_THREADS_MAX] = -1,
+               [_SC_THREAD_ATTR_STACKADDR] = -1,
+               [_SC_THREAD_ATTR_STACKSIZE] = VER,
+               [_SC_THREAD_PRIORITY_SCHEDULING] = -1,
+               [_SC_THREAD_PRIO_INHERIT] = -1,
+               [_SC_THREAD_PRIO_PROTECT] = -1,
+               [_SC_THREAD_PROCESS_SHARED] = VER,
+               [_SC_NPROCESSORS_CONF] = -1,
+               [_SC_NPROCESSORS_ONLN] = -1,
+               [_SC_PHYS_PAGES] = -1,
+               [_SC_AVPHYS_PAGES] = -1,
+               [_SC_ATEXIT_MAX] = -1,
+               [_SC_PASS_MAX] = -1,
+               [_SC_XOPEN_VERSION] = _XOPEN_VERSION,
+               [_SC_XOPEN_XCU_VERSION] = _XOPEN_VERSION,
+               [_SC_XOPEN_UNIX] = -1,
+               [_SC_XOPEN_CRYPT] = -1,
+               [_SC_XOPEN_ENH_I18N] = 1,
+               [_SC_XOPEN_SHM] = 1,
+               [_SC_2_CHAR_TERM] = -1,
+               [_SC_2_C_VERSION] = -1,
+               [_SC_2_UPE] = -1,
+               [_SC_XOPEN_XPG2] = -1,
+               [_SC_XOPEN_XPG3] = -1,
+               [_SC_XOPEN_XPG4] = -1,
+               [_SC_CHAR_BIT] = -1,
+               [_SC_CHAR_MAX] = -1,
+               [_SC_CHAR_MIN] = -1,
+               [_SC_INT_MAX] = -1,
+               [_SC_INT_MIN] = -1,
+               [_SC_LONG_BIT] = -1,
+               [_SC_WORD_BIT] = -1,
+               [_SC_MB_LEN_MAX] = -1,
+               [_SC_NZERO] = NZERO,
+               [_SC_SSIZE_MAX] = -1,
+               [_SC_SCHAR_MAX] = -1,
+               [_SC_SCHAR_MIN] = -1,
+               [_SC_SHRT_MAX] = -1,
+               [_SC_SHRT_MIN] = -1,
+               [_SC_UCHAR_MAX] = -1,
+               [_SC_UINT_MAX] = -1,
+               [_SC_ULONG_MAX] = -1,
+               [_SC_USHRT_MAX] = -1,
+               [_SC_NL_ARGMAX] = -1,
+               [_SC_NL_LANGMAX] = -1,
+               [_SC_NL_MSGMAX] = -1,
+               [_SC_NL_NMAX] = -1,
+               [_SC_NL_SETMAX] = -1,
+               [_SC_NL_TEXTMAX] = -1,
+               [_SC_XBS5_ILP32_OFF32] = -1,
+               [_SC_XBS5_ILP32_OFFBIG] = 2*(sizeof(long)==4)-1,
+               [_SC_XBS5_LP64_OFF64] = 2*(sizeof(long)==8)-1,
+               [_SC_XBS5_LPBIG_OFFBIG] = 2*(sizeof(long)>=8)-1,
+               [_SC_XOPEN_LEGACY] = -1,
+               [_SC_XOPEN_REALTIME] = -1,
+               [_SC_XOPEN_REALTIME_THREADS] = -1,
+               [_SC_ADVISORY_INFO] = -1,
+               [_SC_BARRIERS] = VER,
+               [_SC_BASE] = -1,
+               [_SC_C_LANG_SUPPORT] = -1,
+               [_SC_C_LANG_SUPPORT_R] = -1,
+               [_SC_CLOCK_SELECTION] = VER,
+               [_SC_CPUTIME] = VER,
+               [_SC_THREAD_CPUTIME] = -1,
+               [_SC_DEVICE_IO] = -1,
+               [_SC_DEVICE_SPECIFIC] = -1,
+               [_SC_DEVICE_SPECIFIC_R] = -1,
+               [_SC_FD_MGMT] = -1,
+               [_SC_FIFO] = -1,
+               [_SC_PIPE] = -1,
+               [_SC_FILE_ATTRIBUTES] = -1,
+               [_SC_FILE_LOCKING] = -1,
+               [_SC_FILE_SYSTEM] = -1,
+               [_SC_MONOTONIC_CLOCK] = VER,
+               [_SC_MULTI_PROCESS] = -1,
+               [_SC_SINGLE_PROCESS] = -1,
+               [_SC_NETWORKING] = -1,
+               [_SC_READER_WRITER_LOCKS] = VER,
+               [_SC_SPIN_LOCKS] = VER,
+               [_SC_REGEXP] = 1,
+               [_SC_REGEX_VERSION] = -1,
+               [_SC_SHELL] = 1,
+               [_SC_SIGNALS] = -1,
+               [_SC_SPAWN] = -1,
+               [_SC_SPORADIC_SERVER] = -1,
+               [_SC_THREAD_SPORADIC_SERVER] = -1,
+               [_SC_SYSTEM_DATABASE] = -1,
+               [_SC_SYSTEM_DATABASE_R] = -1,
+               [_SC_TIMEOUTS] = VER,
+               [_SC_TYPED_MEMORY_OBJECTS] = -1,
+               [_SC_USER_GROUPS] = -1,
+               [_SC_USER_GROUPS_R] = -1,
+               [_SC_2_PBS] = -1,
+               [_SC_2_PBS_ACCOUNTING] = -1,
+               [_SC_2_PBS_LOCATE] = -1,
+               [_SC_2_PBS_MESSAGE] = -1,
+               [_SC_2_PBS_TRACK] = -1,
+               [_SC_SYMLOOP_MAX] = SYMLOOP_MAX,
+               [_SC_STREAMS] = 0,
+               [_SC_2_PBS_CHECKPOINT] = -1,
+               [_SC_V6_ILP32_OFF32] = -1,
+               [_SC_V6_ILP32_OFFBIG] = 2*(sizeof(long)==4)-1,
+               [_SC_V6_LP64_OFF64] = 2*(sizeof(long)==8)-1,
+               [_SC_V6_LPBIG_OFFBIG] = 2*(sizeof(long)>=8)-1,
+               [_SC_HOST_NAME_MAX] = HOST_NAME_MAX,
+               [_SC_TRACE] = -1,
+               [_SC_TRACE_EVENT_FILTER] = -1,
+               [_SC_TRACE_INHERIT] = -1,
+               [_SC_TRACE_LOG] = -1,
+
+               [_SC_IPV6] = VER,
+               [_SC_RAW_SOCKETS] = VER,
+               [_SC_V7_ILP32_OFF32] = -1,
+               [_SC_V7_ILP32_OFFBIG] = 2*(sizeof(long)==4)-1,
+               [_SC_V7_LP64_OFF64] = 2*(sizeof(long)==8)-1,
+               [_SC_V7_LPBIG_OFFBIG] = 2*(sizeof(long)>=8)-1,
+               [_SC_SS_REPL_MAX] = -1,
+               [_SC_TRACE_EVENT_NAME_MAX] = -1,
+               [_SC_TRACE_NAME_MAX] = -1,
+               [_SC_TRACE_SYS_MAX] = -1,
+               [_SC_TRACE_USER_EVENT_MAX] = -1,
+               [_SC_XOPEN_STREAMS] = 0,
+               [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
+               [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
+       };
+       if (name > sizeof(values)/sizeof(values[0])) {
+               errno = EINVAL;
+               return -1;
+       } else if (values[name] == VER) {
+               return _POSIX_VERSION;
+       } else if (values[name] == OFLOW) {
+               return ARG_MAX;
+       } else {
+               return values[name];
+       }
+}
diff --git a/src/ctype/__ctype_get_mb_cur_max.c b/src/ctype/__ctype_get_mb_cur_max.c
new file mode 100644 (file)
index 0000000..42e4ee7
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+size_t __ctype_get_mb_cur_max()
+{
+       return 4;
+}
diff --git a/src/ctype/isalnum.c b/src/ctype/isalnum.c
new file mode 100644 (file)
index 0000000..e3d2cf0
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isalnum(int c)
+{
+       return isalpha(c) || isdigit(c);
+}
diff --git a/src/ctype/isalpha.c b/src/ctype/isalpha.c
new file mode 100644 (file)
index 0000000..53e115c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef isalpha
+
+int isalpha(int c)
+{
+       return ((unsigned)c|32)-'a' < 26;
+}
diff --git a/src/ctype/isascii.c b/src/ctype/isascii.c
new file mode 100644 (file)
index 0000000..3af0a10
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isascii(int c)
+{
+       return !(c&~0x7f);
+}
diff --git a/src/ctype/isblank.c b/src/ctype/isblank.c
new file mode 100644 (file)
index 0000000..957400b
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isblank(int c)
+{
+       return (c == ' ' || c == '\t');
+}
diff --git a/src/ctype/iscntrl.c b/src/ctype/iscntrl.c
new file mode 100644 (file)
index 0000000..92ed7f0
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int iscntrl(int c)
+{
+       return (unsigned)c < 0x20 || c == 0x7f;
+}
diff --git a/src/ctype/isdigit.c b/src/ctype/isdigit.c
new file mode 100644 (file)
index 0000000..0bc82a6
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef isdigit
+
+int isdigit(int c)
+{
+       return (unsigned)c-'0' < 10;
+}
diff --git a/src/ctype/isgraph.c b/src/ctype/isgraph.c
new file mode 100644 (file)
index 0000000..98979d1
--- /dev/null
@@ -0,0 +1,4 @@
+int isgraph(int c)
+{
+       return (unsigned)c-0x21 < 0x5e;
+}
diff --git a/src/ctype/islower.c b/src/ctype/islower.c
new file mode 100644 (file)
index 0000000..d72fb21
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef islower
+
+int islower(int c)
+{
+       return (unsigned)c-'a' < 26;
+}
diff --git a/src/ctype/isprint.c b/src/ctype/isprint.c
new file mode 100644 (file)
index 0000000..504e66e
--- /dev/null
@@ -0,0 +1,4 @@
+int isprint(int c)
+{
+       return (unsigned)c-0x20 < 0x5f;
+}
diff --git a/src/ctype/ispunct.c b/src/ctype/ispunct.c
new file mode 100644 (file)
index 0000000..fc45535
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int ispunct(int c)
+{
+       return isgraph(c) && !isalnum(c);
+}
diff --git a/src/ctype/isspace.c b/src/ctype/isspace.c
new file mode 100644 (file)
index 0000000..8e535aa
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isspace(int c)
+{
+       return c == ' ' || (unsigned)c-'\t' < 5;
+}
diff --git a/src/ctype/isupper.c b/src/ctype/isupper.c
new file mode 100644 (file)
index 0000000..f09d88c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef isupper
+
+int isupper(int c)
+{
+       return (unsigned)c-'A' < 26;
+}
diff --git a/src/ctype/iswalnum.c b/src/ctype/iswalnum.c
new file mode 100644 (file)
index 0000000..d3b5667
--- /dev/null
@@ -0,0 +1,9 @@
+#include <wchar.h>
+#include <wctype.h>
+
+#undef iswalnum
+
+int iswalnum(wint_t wc)
+{
+       return (unsigned)wc-'0' < 10 || iswalpha(wc);
+}
diff --git a/src/ctype/iswalpha.c b/src/ctype/iswalpha.c
new file mode 100644 (file)
index 0000000..0f031ea
--- /dev/null
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswalpha(wint_t wc)
+{
+       return (32U|wc)-'a'<26;
+}
diff --git a/src/ctype/iswblank.c b/src/ctype/iswblank.c
new file mode 100644 (file)
index 0000000..bc6196f
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+#include <wctype.h>
+#include <ctype.h>
+
+int iswblank(wint_t wc)
+{
+       return isblank(wc);
+}
diff --git a/src/ctype/iswcntrl.c b/src/ctype/iswcntrl.c
new file mode 100644 (file)
index 0000000..93942b0
--- /dev/null
@@ -0,0 +1,10 @@
+#include <wchar.h>
+#include <wctype.h>
+
+int iswcntrl(wint_t wc)
+{
+       return (unsigned)wc < 32
+           || (unsigned)(wc-0x7f) < 33
+           || (unsigned)(wc-0x2028) < 2
+           || (unsigned)(wc-0xfff9) < 3;
+}
diff --git a/src/ctype/iswctype.c b/src/ctype/iswctype.c
new file mode 100644 (file)
index 0000000..d917975
--- /dev/null
@@ -0,0 +1,63 @@
+#include <wchar.h>
+#include <wctype.h>
+#include <string.h>
+
+#define WCTYPE_ALNUM  1
+#define WCTYPE_ALPHA  2
+#define WCTYPE_BLANK  3
+#define WCTYPE_CNTRL  4
+#define WCTYPE_DIGIT  5
+#define WCTYPE_GRAPH  6
+#define WCTYPE_LOWER  7
+#define WCTYPE_PRINT  8
+#define WCTYPE_PUNCT  9
+#define WCTYPE_SPACE  10
+#define WCTYPE_UPPER  11
+#define WCTYPE_XDIGIT 12
+
+int iswctype(wint_t wc, wctype_t type)
+{
+       switch (type) {
+       case WCTYPE_ALNUM:
+               return iswalnum(wc);
+       case WCTYPE_ALPHA:
+               return iswalpha(wc);
+       case WCTYPE_BLANK:
+               return iswblank(wc);
+       case WCTYPE_CNTRL:
+               return iswcntrl(wc);
+       case WCTYPE_DIGIT:
+               return iswdigit(wc);
+       case WCTYPE_GRAPH:
+               return iswgraph(wc);
+       case WCTYPE_LOWER:
+               return iswlower(wc);
+       case WCTYPE_PRINT:
+               return iswprint(wc);
+       case WCTYPE_PUNCT:
+               return iswpunct(wc);
+       case WCTYPE_SPACE:
+               return iswspace(wc);
+       case WCTYPE_UPPER:
+               return iswupper(wc);
+       case WCTYPE_XDIGIT:
+               return iswxdigit(wc);
+       }
+       return 0;
+}
+
+wctype_t wctype(const char *s)
+{
+       int i;
+       const char *p;
+       /* order must match! */
+       static const char names[] =
+               "alnum\0" "alpha\0" "blank\0"
+               "cntrl\0" "digit\0" "graph\0"
+               "lower\0" "print\0" "punct\0"
+               "space\0" "upper\0" "xdigit";
+       for (i=1, p=names; *p; i++, p+=6)
+               if (*s == *p && !strcmp(s, p))
+                       return i;
+       return 0;
+}
diff --git a/src/ctype/iswdigit.c b/src/ctype/iswdigit.c
new file mode 100644 (file)
index 0000000..0487145
--- /dev/null
@@ -0,0 +1,9 @@
+#include <wchar.h>
+#include <wctype.h>
+
+#undef iswdigit
+
+int iswdigit(wint_t wc)
+{
+       return (unsigned)wc-'0' < 10;
+}
diff --git a/src/ctype/iswgraph.c b/src/ctype/iswgraph.c
new file mode 100644 (file)
index 0000000..fdc9785
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wctype.h>
+
+int iswgraph(wint_t wc)
+{
+       /* ISO C defines this function as: */
+       return !iswspace(wc) && iswprint(wc);
+}
diff --git a/src/ctype/iswlower.c b/src/ctype/iswlower.c
new file mode 100644 (file)
index 0000000..0a568e7
--- /dev/null
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswlower(wint_t wc)
+{
+       return towupper(wc) != wc;
+}
diff --git a/src/ctype/iswprint.c b/src/ctype/iswprint.c
new file mode 100644 (file)
index 0000000..7717671
--- /dev/null
@@ -0,0 +1,10 @@
+#include <wctype.h>
+
+int iswprint(wint_t wc)
+{
+       unsigned c = wc;
+       /* assume any non-control, non-illegal codepoint is printable */
+       if (c>0x10ffff || c-0xd800<0x800 || (c&0xfffe)==0xfffe || iswcntrl(c))
+               return 0;
+       return 1;
+}
diff --git a/src/ctype/iswpunct.c b/src/ctype/iswpunct.c
new file mode 100644 (file)
index 0000000..1414c30
--- /dev/null
@@ -0,0 +1,138 @@
+#include <wctype.h>
+#include <inttypes.h>
+
+/* The below data is derived from classes (P.|Sm) plus Pattern_Syntax */
+
+#define R(a,b) { (b), (b)-(a) }
+
+static const struct range {
+       uint32_t base:20;
+       uint32_t len:12;
+} ranges[] = {
+R(0x21, 0x2f),
+R(0x3a, 0x40),
+R(0x5b, 0x60),
+R(0x7b, 0x7e),
+R(0xa1, 0xa7),
+R(0xa9, 0xa9),
+R(0xab, 0xac),
+R(0xae, 0xae),
+R(0xb0, 0xb1),
+R(0xb6, 0xb7),
+R(0xbb, 0xbb),
+R(0xbf, 0xbf),
+R(0xd7, 0xd7),
+R(0xf7, 0xf7),
+R(0x37e, 0x37e),
+R(0x387, 0x387),
+R(0x3f6, 0x3f6),
+R(0x55a, 0x55f),
+R(0x589, 0x58a),
+R(0x5be, 0x5be),
+R(0x5c0, 0x5c0),
+R(0x5c3, 0x5c3),
+R(0x5c6, 0x5c6),
+R(0x5f3, 0x5f4),
+R(0x606, 0x60a),
+R(0x60c, 0x60d),
+R(0x61b, 0x61b),
+R(0x61e, 0x61f),
+R(0x66a, 0x66d),
+R(0x6d4, 0x6d4),
+R(0x700, 0x70d),
+R(0x7f7, 0x7f9),
+R(0x964, 0x965),
+R(0x970, 0x970),
+R(0xdf4, 0xdf4),
+R(0xe4f, 0xe4f),
+R(0xe5a, 0xe5b),
+R(0xf04, 0xf12),
+R(0xf3a, 0xf3d),
+R(0xf85, 0xf85),
+R(0xfd0, 0xfd4),
+R(0x104a, 0x104f),
+R(0x10fb, 0x10fb),
+R(0x1361, 0x1368),
+R(0x166d, 0x166e),
+R(0x1680, 0x1680),
+R(0x169b, 0x169c),
+R(0x16eb, 0x16ed),
+R(0x1735, 0x1736),
+R(0x17d4, 0x17d6),
+R(0x17d8, 0x17da),
+R(0x1800, 0x180a),
+R(0x180e, 0x180e),
+R(0x1944, 0x1945),
+R(0x19de, 0x19df),
+R(0x1a1e, 0x1a1f),
+R(0x1b5a, 0x1b60),
+R(0x1c3b, 0x1c3f),
+R(0x1c7e, 0x1c7f),
+R(0x2010, 0x2027),
+R(0x2030, 0x205e),
+R(0x207a, 0x207e),
+R(0x208a, 0x208e),
+R(0x2140, 0x2144),
+R(0x214b, 0x214b),
+R(0x2190, 0x245f),
+R(0x2500, 0x2775),
+R(0x2794, 0x2bff),
+R(0x2cf9, 0x2cfc),
+R(0x2cfe, 0x2cff),
+R(0x2e00, 0x2e7f),
+R(0x3001, 0x3003),
+R(0x3008, 0x3020),
+R(0x3030, 0x3030),
+R(0x303d, 0x303d),
+R(0x30a0, 0x30a0),
+R(0x30fb, 0x30fb),
+R(0xa60d, 0xa60f),
+R(0xa874, 0xa877),
+R(0xa8ce, 0xa8cf),
+R(0xa92e, 0xa92f),
+R(0xa95f, 0xa95f),
+R(0xfb29, 0xfb29),
+R(0xfd3e, 0xfd3f),
+R(0xfe10, 0xfe19),
+R(0xfe30, 0xfe52),
+R(0xfe54, 0xfe66),
+R(0xfe68, 0xfe68),
+R(0xfe6a, 0xfe6b),
+R(0xff01, 0xff03),
+R(0xff05, 0xff0f),
+R(0xff1a, 0xff20),
+R(0xff3b, 0xff3d),
+R(0xff3f, 0xff3f),
+R(0xff5b, 0xff65),
+R(0xffe2, 0xffe2),
+R(0xffe9, 0xffec),
+R(0x10100, 0x10101),
+R(0x1039f, 0x1039f),
+R(0x103d0, 0x103d0),
+R(0x1091f, 0x1091f),
+R(0x1093f, 0x1093f),
+R(0x10a50, 0x10a58),
+R(0x12470, 0x12473),
+R(0x1d6c1, 0x1d6c1),
+R(0x1d6db, 0x1d6db),
+R(0x1d6fb, 0x1d6fb),
+R(0x1d715, 0x1d715),
+R(0x1d735, 0x1d735),
+R(0x1d74f, 0x1d74f),
+R(0x1d76f, 0x1d76f),
+R(0x1d789, 0x1d789),
+R(0x1d7a9, 0x1d7a9),
+R(0x1d7c3, 0x1d7c3),
+};
+
+int iswpunct(wint_t wc)
+{
+       unsigned c = wc;
+       int a = 0;
+       int n = sizeof ranges / sizeof ranges[0];
+       do {
+               n >>= 1;
+               a += n+1 & (signed)(ranges[a+n].base-c)>>31;
+       } while (n);
+       return ranges[a].base-c <= ranges[a].len;
+}
diff --git a/src/ctype/iswspace.c b/src/ctype/iswspace.c
new file mode 100644 (file)
index 0000000..68a1743
--- /dev/null
@@ -0,0 +1,15 @@
+#include <wchar.h>
+#include <wctype.h>
+#include <ctype.h>
+
+int iswspace(wint_t wc)
+{
+       static const wchar_t spaces[] = {
+               ' ', '\t', '\n', '\r', 11, 12,  0x0085,
+               0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
+               0x2006, 0x2008, 0x2009, 0x200a, 0x200b,
+               0x2028, 0x2029, 0x2050, 0x3000, 0
+       };
+       if (wcschr(spaces, wc)) return 1;
+       return 0;
+}
diff --git a/src/ctype/iswupper.c b/src/ctype/iswupper.c
new file mode 100644 (file)
index 0000000..eae59a7
--- /dev/null
@@ -0,0 +1,6 @@
+#include <wctype.h>
+
+int iswupper(wint_t wc)
+{
+       return towlower(wc) != wc;
+}
diff --git a/src/ctype/iswxdigit.c b/src/ctype/iswxdigit.c
new file mode 100644 (file)
index 0000000..229a469
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wchar.h>
+#include <wctype.h>
+
+int iswxdigit(wint_t wc)
+{
+       return (unsigned)(wc-'0') < 10 || (unsigned)((wc|32)-'a') < 6;
+}
diff --git a/src/ctype/isxdigit.c b/src/ctype/isxdigit.c
new file mode 100644 (file)
index 0000000..ae68a3d
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isxdigit(int c)
+{
+       return isdigit(c) || ((unsigned)c|32)-'a' < 6;
+}
diff --git a/src/ctype/toascii.c b/src/ctype/toascii.c
new file mode 100644 (file)
index 0000000..f0e48e8
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+/* nonsense function that should NEVER be used! */
+int toascii(int c)
+{
+       return c & 0x7f;
+}
diff --git a/src/ctype/tolower.c b/src/ctype/tolower.c
new file mode 100644 (file)
index 0000000..b56f3c5
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int tolower(int c)
+{
+       if (isupper(c)) return c | 32;
+       return c;
+}
diff --git a/src/ctype/toupper.c b/src/ctype/toupper.c
new file mode 100644 (file)
index 0000000..1799f03
--- /dev/null
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int toupper(int c)
+{
+       if (islower(c)) return c & 0x5f;
+       return c;
+}
diff --git a/src/ctype/towctrans.c b/src/ctype/towctrans.c
new file mode 100644 (file)
index 0000000..0b1eed0
--- /dev/null
@@ -0,0 +1,246 @@
+#include <wchar.h>
+#include <wctype.h>
+#include <stdio.h>
+
+#define CASEMAP(u1,u2,l) { (u1), (l)-(u1), (u2)-(u1)+1 }
+#define CASELACE(u1,u2) CASEMAP((u1),(u2),(u1)+1)
+
+static const struct {
+       unsigned short upper;
+       signed char lower;
+       unsigned char len;
+} casemaps[] = {
+       CASEMAP('A','Z','a'),
+       CASEMAP(0xc0,0xde,0xe0),
+
+       CASELACE(0x0100,0x012e),
+       CASELACE(0x0132,0x0136),
+       CASELACE(0x0139,0x0147),
+       CASELACE(0x014a,0x0176),
+       CASELACE(0x0179,0x017d),
+
+       CASELACE(0x370,0x372),
+       CASEMAP(0x391,0x3a1,0x3b1),
+       CASEMAP(0x3a3,0x3ab,0x3c3),
+       CASEMAP(0x400,0x40f,0x450),
+       CASEMAP(0x410,0x42f,0x430),
+
+       CASELACE(0x460,0x480),
+       CASELACE(0x48a,0x4be),
+       CASELACE(0x4c1,0x4cd),
+       CASELACE(0x4d0,0x50e),
+
+       CASEMAP(0x531,0x556,0x561),
+
+       CASELACE(0x01a0,0x01a4),
+       CASELACE(0x01b3,0x01b5),
+       CASELACE(0x01cd,0x01db),
+       CASELACE(0x01de,0x01ee),
+       CASELACE(0x01f8,0x021e),
+       CASELACE(0x0222,0x0232),
+       CASELACE(0x03d8,0x03ee),
+
+       CASELACE(0x1e00,0x1e94),
+       CASELACE(0x1ea0,0x1efe),
+
+       CASEMAP(0x1f08,0x1f0f,0x1f00),
+       CASEMAP(0x1f18,0x1f1d,0x1f10),
+       CASEMAP(0x1f28,0x1f2f,0x1f20),
+       CASEMAP(0x1f38,0x1f3f,0x1f30),
+       CASEMAP(0x1f48,0x1f4d,0x1f40),
+
+       CASEMAP(0x1f68,0x1f6f,0x1f60),
+       CASEMAP(0x1f88,0x1f8f,0x1f80),
+       CASEMAP(0x1f98,0x1f9f,0x1f90),
+       CASEMAP(0x1fa8,0x1faf,0x1fa0),
+       CASEMAP(0x1fb8,0x1fb9,0x1fb0),
+       CASEMAP(0x1fba,0x1fbb,0x1f70),
+       CASEMAP(0x1fc8,0x1fcb,0x1f72),
+       CASEMAP(0x1fd8,0x1fd9,0x1fd0),
+       CASEMAP(0x1fda,0x1fdb,0x1f76),
+       CASEMAP(0x1fe8,0x1fe9,0x1fe0),
+       CASEMAP(0x1fea,0x1feb,0x1f7a),
+       CASEMAP(0x1ff8,0x1ff9,0x1f78),
+       CASEMAP(0x1ffa,0x1ffb,0x1f7c),
+
+       CASELACE(0x246,0x24e),
+       CASELACE(0x510,0x512),
+       CASEMAP(0x2160,0x216f,0x2170),
+       CASEMAP(0x2c00,0x2c2e,0x2c30),
+       CASELACE(0x2c67,0x2c6b),
+       CASELACE(0x2c80,0x2ce2),
+
+       CASELACE(0xa722,0xa72e),
+       CASELACE(0xa732,0xa76e),
+       CASELACE(0xa779,0xa77b),
+       CASELACE(0xa77e,0xa786),
+
+       CASEMAP(0xff21,0xff3a,0xff41),
+       { 0,0,0 }
+};
+
+static const unsigned short pairs[][2] = {
+       { 'I',    0x0131 },
+       { 'S',    0x017f },
+       { 0x0130, 'i'    },
+       { 0x0178, 0x00ff },
+       { 0x0181, 0x0253 },
+       { 0x0182, 0x0183 },
+       { 0x0184, 0x0185 },
+       { 0x0186, 0x0254 },
+       { 0x0187, 0x0188 },
+       { 0x0189, 0x0256 },
+       { 0x018a, 0x0257 },
+       { 0x018b, 0x018c },
+       { 0x018e, 0x01dd },
+       { 0x018f, 0x0259 },
+       { 0x0190, 0x025b },
+       { 0x0191, 0x0192 },
+       { 0x0193, 0x0260 },
+       { 0x0194, 0x0263 },
+       { 0x0196, 0x0269 },
+       { 0x0197, 0x0268 },
+       { 0x0198, 0x0199 },
+       { 0x019c, 0x026f },
+       { 0x019d, 0x0272 },
+       { 0x019f, 0x0275 },
+       { 0x01a6, 0x0280 },
+       { 0x01a7, 0x01a8 },
+       { 0x01a9, 0x0283 },
+       { 0x01ac, 0x01ad },
+       { 0x01ae, 0x0288 },
+       { 0x01af, 0x01b0 },
+       { 0x01b1, 0x028a },
+       { 0x01b2, 0x028b },
+       { 0x01b7, 0x0292 },
+       { 0x01b8, 0x01b9 },
+       { 0x01bc, 0x01bd },
+       { 0x01c4, 0x01c6 },
+       { 0x01c4, 0x01c5 },
+       { 0x01c5, 0x01c6 },
+       { 0x01c7, 0x01c9 },
+       { 0x01c7, 0x01c8 },
+       { 0x01c8, 0x01c9 },
+       { 0x01ca, 0x01cc },
+       { 0x01ca, 0x01cb },
+       { 0x01cb, 0x01cc },
+       { 0x01f1, 0x01f3 },
+       { 0x01f1, 0x01f2 },
+       { 0x01f2, 0x01f3 },
+       { 0x01f4, 0x01f5 },
+       { 0x01f6, 0x0195 },
+       { 0x01f7, 0x01bf },
+       { 0x0220, 0x019e },
+       { 0x0386, 0x03ac },
+       { 0x0388, 0x03ad },
+       { 0x0389, 0x03ae },
+       { 0x038a, 0x03af },
+       { 0x038c, 0x03cc },
+       { 0x038e, 0x03cd },
+       { 0x038f, 0x03ce },
+       { 0x0399, 0x0345 },
+       { 0x0399, 0x1fbe },
+       { 0x03a3, 0x03c2 },
+       { 0x03f7, 0x03f8 },
+       { 0x03fa, 0x03fb },
+       { 0x1e60, 0x1e9b },
+
+       { 0x1f59, 0x1f51 },
+       { 0x1f5b, 0x1f53 },
+       { 0x1f5d, 0x1f55 },
+       { 0x1f5f, 0x1f57 },
+       { 0x1fbc, 0x1fb3 },
+       { 0x1fcc, 0x1fc3 },
+       { 0x1fec, 0x1fe5 },
+       { 0x1ffc, 0x1ff3 },
+
+       { 0x23a, 0x2c65 },
+       { 0x23b, 0x23c },
+       { 0x23d, 0x19a },
+       { 0x23e, 0x2c66 },
+       { 0x241, 0x242 },
+       { 0x243, 0x180 },
+       { 0x244, 0x289 },
+       { 0x245, 0x28c },
+       { 0x3f4, 0x3b8 },
+       { 0x3f9, 0x3f2 },
+       { 0x3fd, 0x37b },
+       { 0x3fe, 0x37c },
+       { 0x3ff, 0x37d },
+       { 0x4c0, 0x4cf },
+
+       { 0x2126, 0x3c9 },
+       { 0x212a, 'k' },
+       { 0x212b, 0xe5 },
+       { 0x2132, 0x214e },
+       { 0x2183, 0x2184 },
+       { 0x2c60, 0x2c61 },
+       { 0x2c62, 0x26b },
+       { 0x2c63, 0x1d7d },
+       { 0x2c64, 0x27d },
+       { 0x2c6d, 0x251 },
+       { 0x2c6e, 0x271 },
+       { 0x2c6f, 0x250 },
+       { 0x2c72, 0x2c73 },
+       { 0x2c75, 0x2c76 },
+
+       { 0xa77d, 0x1d79 },
+
+       /* bogus greek 'symbol' letters */
+       { 0x376, 0x377 },
+       { 0x39c, 0xb5 },
+       { 0x392, 0x3d0 },
+       { 0x398, 0x3d1 },
+       { 0x3a6, 0x3d5 },
+       { 0x3a0, 0x3d6 },
+       { 0x39a, 0x3f0 },
+       { 0x3a1, 0x3f1 },
+       { 0x395, 0x3f5 },
+       { 0x3cf, 0x3d7 },
+
+       { 0,0 }
+};
+
+
+static wchar_t __towcase(wchar_t wc, int lower)
+{
+       int i;
+       int lmul = 2*lower-1;
+       int lmask = lower-1;
+       if ((unsigned)wc - 0x10400 < 0x50)
+               return wc + lmul*0x28;
+       /* no letters with case in these large ranges */
+       if (!iswalpha(wc)
+        || (unsigned)wc - 0x0600 <= 0x0fff-0x0600
+        || (unsigned)wc - 0x2e00 <= 0xa6ff-0x2e00
+        || (unsigned)wc - 0xa800 <= 0xfeff-0xa800)
+               return wc;
+       /* special case because the diff between upper/lower is too big */
+       if ((unsigned)wc - 0x10a0 < 0x26 || (unsigned)wc - 0x2d00 < 0x26)
+               return wc + lmul*(0x2d00-0x10a0);
+       for (i=0; casemaps[i].len; i++) {
+               int base = casemaps[i].upper + (lmask & casemaps[i].lower);
+               if ((unsigned)wc-base < casemaps[i].len) {
+                       if (casemaps[i].lower == 1)
+                               return wc + lower - ((wc-casemaps[i].upper)&1);
+                       return wc + lmul*casemaps[i].lower;
+               }
+       }
+       for (i=0; pairs[i][1-lower]; i++) {
+               if (pairs[i][1-lower] == wc)
+                       return pairs[i][lower];
+       }
+       if ((unsigned)wc - 0x10428 + (lower<<5) + (lower<<3) < 0x28)
+               return wc - 0x28 + (lower<<10) + (lower<<6);
+       return wc;
+}
+
+wint_t towupper(wint_t wc)
+{
+       return __towcase(wc, 0);
+}
+
+wint_t towlower(wint_t wc)
+{
+       return __towcase(wc, 1);
+}
diff --git a/src/ctype/wcswidth.c b/src/ctype/wcswidth.c
new file mode 100644 (file)
index 0000000..5c8a5a4
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+int wcswidth(const wchar_t *wcs, size_t n)
+{
+       int l=0, k=0;
+       for (; n-- && *wcs && (k = wcwidth(*wcs)) >= 0; l+=k, wcs++);
+       return (k < 0) ? k : l;
+}
diff --git a/src/ctype/wctrans.c b/src/ctype/wctrans.c
new file mode 100644 (file)
index 0000000..03e9fd6
--- /dev/null
@@ -0,0 +1,16 @@
+#include <wctype.h>
+#include <string.h>
+
+wctrans_t wctrans(const char *class)
+{
+       if (!strcmp(class, "toupper")) return 1;
+       if (!strcmp(class, "tolower")) return 2;
+       return 0;
+}
+
+wint_t towctrans(wint_t wc, wctrans_t trans)
+{
+       if (trans == 1) return towupper(wc);
+       if (trans == 2) return towlower(wc);
+       return wc;
+}
diff --git a/src/ctype/wcwidth.c b/src/ctype/wcwidth.c
new file mode 100644 (file)
index 0000000..ebc560a
--- /dev/null
@@ -0,0 +1,185 @@
+#include <inttypes.h>
+#include <wchar.h>
+
+#define R(a,b,w) { (b), (w)/2, (b)-(a) }
+
+static const struct range {
+       uint32_t base:20;
+       uint32_t width:1;
+       uint32_t len:11;
+} ranges[] = {
+       R(0x0300, 0x036F, 0),
+       R(0x0483, 0x0486, 0),
+       R(0x0488, 0x0489, 0),
+       R(0x0591, 0x05BD, 0),
+       R(0x05BF, 0x05BF, 0),
+       R(0x05C1, 0x05C2, 0),
+       R(0x05C4, 0x05C5, 0),
+       R(0x05C7, 0x05C7, 0),
+       R(0x0600, 0x0603, 0),
+       R(0x0610, 0x0615, 0),
+       R(0x064B, 0x065E, 0),
+       R(0x0670, 0x0670, 0),
+       R(0x06D6, 0x06E4, 0),
+       R(0x06E7, 0x06E8, 0),
+       R(0x06EA, 0x06ED, 0),
+       R(0x070F, 0x070F, 0),
+       R(0x0711, 0x0711, 0),
+       R(0x0730, 0x074A, 0),
+       R(0x07A6, 0x07B0, 0),
+       R(0x07EB, 0x07F3, 0),
+       R(0x0901, 0x0902, 0),
+       R(0x093C, 0x093C, 0),
+       R(0x0941, 0x0948, 0),
+       R(0x094D, 0x094D, 0),
+       R(0x0951, 0x0954, 0),
+       R(0x0962, 0x0963, 0),
+       R(0x0981, 0x0981, 0),
+       R(0x09BC, 0x09BC, 0),
+       R(0x09C1, 0x09C4, 0),
+       R(0x09CD, 0x09CD, 0),
+       R(0x09E2, 0x09E3, 0),
+       R(0x0A01, 0x0A02, 0),
+       R(0x0A3C, 0x0A3C, 0),
+       R(0x0A41, 0x0A42, 0),
+       R(0x0A47, 0x0A48, 0),
+       R(0x0A4B, 0x0A4D, 0),
+       R(0x0A70, 0x0A71, 0),
+       R(0x0A81, 0x0A82, 0),
+       R(0x0ABC, 0x0ABC, 0),
+       R(0x0AC1, 0x0AC5, 0),
+       R(0x0AC7, 0x0AC8, 0),
+       R(0x0ACD, 0x0ACD, 0),
+       R(0x0AE2, 0x0AE3, 0),
+       R(0x0B01, 0x0B01, 0),
+       R(0x0B3C, 0x0B3C, 0),
+       R(0x0B3F, 0x0B3F, 0),
+       R(0x0B41, 0x0B43, 0),
+       R(0x0B4D, 0x0B4D, 0),
+       R(0x0B56, 0x0B56, 0),
+       R(0x0B82, 0x0B82, 0),
+       R(0x0BC0, 0x0BC0, 0),
+       R(0x0BCD, 0x0BCD, 0),
+       R(0x0C3E, 0x0C40, 0),
+       R(0x0C46, 0x0C48, 0),
+       R(0x0C4A, 0x0C4D, 0),
+       R(0x0C55, 0x0C56, 0),
+       R(0x0CBC, 0x0CBC, 0),
+       R(0x0CBF, 0x0CBF, 0),
+       R(0x0CC6, 0x0CC6, 0),
+       R(0x0CCC, 0x0CCD, 0),
+       R(0x0CE2, 0x0CE3, 0),
+       R(0x0D41, 0x0D43, 0),
+       R(0x0D4D, 0x0D4D, 0),
+       R(0x0DCA, 0x0DCA, 0),
+       R(0x0DD2, 0x0DD4, 0),
+       R(0x0DD6, 0x0DD6, 0),
+       R(0x0E31, 0x0E31, 0),
+       R(0x0E34, 0x0E3A, 0),
+       R(0x0E47, 0x0E4E, 0),
+       R(0x0EB1, 0x0EB1, 0),
+       R(0x0EB4, 0x0EB9, 0),
+       R(0x0EBB, 0x0EBC, 0),
+       R(0x0EC8, 0x0ECD, 0),
+       R(0x0F18, 0x0F19, 0),
+       R(0x0F35, 0x0F35, 0),
+       R(0x0F37, 0x0F37, 0),
+       R(0x0F39, 0x0F39, 0),
+       R(0x0F71, 0x0F7E, 0),
+       R(0x0F80, 0x0F84, 0),
+       R(0x0F86, 0x0F87, 0),
+       R(0x0F90, 0x0F97, 0),
+       R(0x0F99, 0x0FBC, 0),
+       R(0x0FC6, 0x0FC6, 0),
+       R(0x102D, 0x1030, 0),
+       R(0x1032, 0x1032, 0),
+       R(0x1036, 0x1037, 0),
+       R(0x1039, 0x1039, 0),
+       R(0x1058, 0x1059, 0),
+       R(0x1100, 0x115F, 2),
+       R(0x1160, 0x11FF, 0),
+       R(0x135F, 0x135F, 0),
+       R(0x1712, 0x1714, 0),
+       R(0x1732, 0x1734, 0),
+       R(0x1752, 0x1753, 0),
+       R(0x1772, 0x1773, 0),
+       R(0x17B4, 0x17B5, 0),
+       R(0x17B7, 0x17BD, 0),
+       R(0x17C6, 0x17C6, 0),
+       R(0x17C9, 0x17D3, 0),
+       R(0x17DD, 0x17DD, 0),
+       R(0x180B, 0x180D, 0),
+       R(0x18A9, 0x18A9, 0),
+       R(0x1920, 0x1922, 0),
+       R(0x1927, 0x1928, 0),
+       R(0x1932, 0x1932, 0),
+       R(0x1939, 0x193B, 0),
+       R(0x1A17, 0x1A18, 0),
+       R(0x1B00, 0x1B03, 0),
+       R(0x1B34, 0x1B34, 0),
+       R(0x1B36, 0x1B3A, 0),
+       R(0x1B3C, 0x1B3C, 0),
+       R(0x1B42, 0x1B42, 0),
+       R(0x1B6B, 0x1B73, 0),
+       R(0x1DC0, 0x1DCA, 0),
+       R(0x1DFE, 0x1DFF, 0),
+       R(0x200B, 0x200F, 0),
+       R(0x202A, 0x202E, 0),
+       R(0x2060, 0x2063, 0),
+       R(0x206A, 0x206F, 0),
+       R(0x20D0, 0x20EF, 0),
+       R(0x2329, 0x232A, 2),
+       R(0x2E80, 0x3029, 2),
+       R(0x302A, 0x302F, 0),
+       R(0x3030, 0x303E, 2),
+       R(0x3099, 0x309A, 0),
+       R(0xA806, 0xA806, 0),
+       R(0xA80B, 0xA80B, 0),
+       R(0xA825, 0xA826, 0),
+       R(0xF900, 0xFAFF, 2),
+       R(0xFB1E, 0xFB1E, 0),
+       R(0xFE00, 0xFE0F, 0),
+       R(0xFE20, 0xFE23, 0),
+       R(0xFE30, 0xFE6F, 2),
+       R(0xFEFF, 0xFEFF, 0),
+       R(0xFF00, 0xFF60, 2),
+       R(0xFFE0, 0xFFE6, 2),
+       R(0x10A01, 0x10A03, 0),
+       R(0x10A05, 0x10A06, 0),
+       R(0x10A0C, 0x10A0F, 0),
+       R(0x10A38, 0x10A3A, 0),
+       R(0x10A3F, 0x10A3F, 0),
+       R(0x1D167, 0x1D169, 0),
+       R(0x1D173, 0x1D182, 0),
+       R(0x1D185, 0x1D18B, 0),
+       R(0x1D1AA, 0x1D1AD, 0),
+       R(0x1D242, 0x1D244, 0),
+       R(0xE0001, 0xE0001, 0),
+       R(0xE0020, 0xE007F, 0),
+       R(0xE0100, 0xE01EF, 0),
+};
+
+/* Note: because the len field is only 10 bits, we must special-case
+ * the two huge ranges of full width characters and exclude them
+ * from the binary search table. */
+
+int wcwidth(wchar_t wc)
+{
+       int a, n;
+       uint32_t c = wc;
+
+       if (c-0x20 < 0x5f) return 1;
+       if (!iswprint(c)) return wc ? -1 : 0;
+       if (c-0x20000 < 0x20000) return 2;
+
+       /* The following code is a branchless binary search. */
+       a = 0;
+       n = sizeof ranges / sizeof ranges[0];
+       do {
+               n >>= 1;
+               a += n+1 & (signed)(ranges[a+n].base-c)>>31;
+       } while (n);
+       if (ranges[a].base-c <= ranges[a].len)
+               return 2*ranges[a].width;
+       return 1 + (c-0x3040 < 0xd800-0x3040);
+}
diff --git a/src/dirent/__dirent.h b/src/dirent/__dirent.h
new file mode 100644 (file)
index 0000000..07b3ee6
--- /dev/null
@@ -0,0 +1,9 @@
+struct __DIR_s
+{
+       int lock;
+       int fd;
+       off_t tell;
+       int buf_pos;
+       int buf_end;
+       char buf[2048];
+};
diff --git a/src/dirent/__getdents.c b/src/dirent/__getdents.c
new file mode 100644 (file)
index 0000000..4195430
--- /dev/null
@@ -0,0 +1,12 @@
+#include <dirent.h>
+#include "syscall.h"
+#include "libc.h"
+
+int __getdents(int fd, struct dirent *buf, size_t len)
+{
+       return syscall3(__NR_getdents64, fd, (long)buf, len);
+}
+
+weak_alias(__getdents, getdents);
+
+LFS64(getdents);
diff --git a/src/dirent/alphasort.c b/src/dirent/alphasort.c
new file mode 100644 (file)
index 0000000..42050fb
--- /dev/null
@@ -0,0 +1,10 @@
+#include <string.h>
+#include <dirent.h>
+#include "libc.h"
+
+int alphasort(const struct dirent **a, const struct dirent **b)
+{
+       return strcoll((*a)->d_name, (*b)->d_name);
+}
+
+LFS64(alphasort);
diff --git a/src/dirent/closedir.c b/src/dirent/closedir.c
new file mode 100644 (file)
index 0000000..81e9591
--- /dev/null
@@ -0,0 +1,11 @@
+#include <dirent.h>
+#include <unistd.h>
+#include "__dirent.h"
+#include "libc.h"
+
+int closedir(DIR *dir)
+{
+       int ret = close(dir->fd);
+       free(dir);
+       return ret;
+}
diff --git a/src/dirent/dirfd.c b/src/dirent/dirfd.c
new file mode 100644 (file)
index 0000000..6c86007
--- /dev/null
@@ -0,0 +1,7 @@
+#include <dirent.h>
+#include "__dirent.h"
+
+int dirfd(DIR *d)
+{
+       return d->fd;
+}
diff --git a/src/dirent/fdopendir.c b/src/dirent/fdopendir.c
new file mode 100644 (file)
index 0000000..c4b8e61
--- /dev/null
@@ -0,0 +1,26 @@
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include "__dirent.h"
+
+DIR *fdopendir(int fd)
+{
+       DIR *dir;
+       struct stat st;
+
+       if (fstat(fd, &st) < 0 || !S_ISDIR(st.st_mode)) {
+               errno = ENOTDIR;
+               return 0;
+       }
+       if (!(dir = calloc(1, sizeof *dir))) {
+               return 0;
+       }
+
+       fcntl(fd, F_SETFD, FD_CLOEXEC);
+       dir->fd = fd;
+       return dir;
+}
diff --git a/src/dirent/opendir.c b/src/dirent/opendir.c
new file mode 100644 (file)
index 0000000..cefe6ce
--- /dev/null
@@ -0,0 +1,25 @@
+#define _GNU_SOURCE
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include "__dirent.h"
+
+DIR *opendir(const char *name)
+{
+       int fd;
+       DIR *dir;
+
+       if ((fd = open(name, O_RDONLY|O_DIRECTORY)) < 0)
+               return 0;
+       fcntl(fd, F_SETFD, FD_CLOEXEC);
+       if (!(dir = calloc(1, sizeof *dir))) {
+               close(fd);
+               return 0;
+       }
+       dir->fd = fd;
+       return dir;
+}
diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c
new file mode 100644 (file)
index 0000000..1aeb25a
--- /dev/null
@@ -0,0 +1,32 @@
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "__dirent.h"
+#include "syscall.h"
+#include "libc.h"
+
+int __getdents(int, struct dirent *, size_t);
+
+struct dirent *readdir(DIR *dir)
+{
+       struct dirent *de;
+       
+       if (dir->buf_pos >= dir->buf_end) {
+               int len = __getdents(dir->fd, (void *)dir->buf, sizeof dir->buf);
+               if (len < 0) {
+                       dir->lock = 0;
+                       return NULL;
+               } else if (len == 0) return 0;
+               dir->buf_end = len;
+               dir->buf_pos = 0;
+       }
+       de = (void *)(dir->buf + dir->buf_pos);
+       dir->buf_pos += de->d_reclen;
+       dir->tell = de->d_off;
+       return de;
+}
+
+LFS64(readdir);
diff --git a/src/dirent/readdir_r.c b/src/dirent/readdir_r.c
new file mode 100644 (file)
index 0000000..58f6032
--- /dev/null
@@ -0,0 +1,30 @@
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "__dirent.h"
+#include "libc.h"
+
+int readdir_r(DIR *dir, struct dirent *buf, struct dirent **result)
+{
+       struct dirent *de;
+       int errno_save = errno;
+       int ret;
+       
+       LOCK(&dir->lock);
+       errno = 0;
+       de = readdir(dir);
+       if ((ret = errno)) {
+               UNLOCK(&dir->lock);
+               return ret;
+       }
+       errno = errno_save;
+       if (de) memcpy(buf, de, de->d_reclen);
+       else buf = NULL;
+
+       UNLOCK(&dir->lock);
+       *result = buf;
+       return 0;
+}
+
+LFS64_2(readdir_r, readdir64_r);
diff --git a/src/dirent/rewinddir.c b/src/dirent/rewinddir.c
new file mode 100644 (file)
index 0000000..c6138f7
--- /dev/null
@@ -0,0 +1,13 @@
+#include <dirent.h>
+#include <unistd.h>
+#include "__dirent.h"
+#include "libc.h"
+
+void rewinddir(DIR *dir)
+{
+       LOCK(&dir->lock);
+       lseek(dir->fd, 0, SEEK_SET);
+       dir->buf_pos = dir->buf_end = 0;
+       dir->tell = 0;
+       UNLOCK(&dir->lock);
+}
diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c
new file mode 100644 (file)
index 0000000..6a0a999
--- /dev/null
@@ -0,0 +1,50 @@
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stddef.h>
+#include <libc.h>
+
+int scandir(const char *path, struct dirent ***res,
+       int (*sel)(const struct dirent *),
+       int (*cmp)(const struct dirent **, const struct dirent **))
+{
+       DIR *d = opendir(path);
+       struct dirent *de, **names=0, **tmp;
+       size_t cnt=0, len=0, size;
+       int old_errno = errno;
+
+       if (!d) return -1;
+
+       while ((errno=0), (de = readdir(d))) {
+               if (sel && !sel(de)) continue;
+               if (cnt >= len) {
+                       len = 2*len+1;
+                       if (len > SIZE_MAX/sizeof *names) break;
+                       tmp = realloc(names, len * sizeof *names);
+                       if (!tmp) break;
+                       names = tmp;
+               }
+               size = offsetof(struct dirent,d_name) + strlen(de->d_name) + 1;
+               names[cnt] = malloc(size);
+               if (!names[cnt]) break;
+               memcpy(names[cnt++], de, size);
+       }
+
+       closedir(d);
+
+       if (errno) {
+               old_errno = errno;
+               if (names) while (cnt-->0) free(names[cnt]);
+               free(names);
+               errno = old_errno;
+               return -1;
+       }
+
+       if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp);
+       *res = names;
+       return cnt;
+}
+
+LFS64(scandir);
diff --git a/src/dirent/seekdir.c b/src/dirent/seekdir.c
new file mode 100644 (file)
index 0000000..81a0e33
--- /dev/null
@@ -0,0 +1,12 @@
+#include <dirent.h>
+#include <unistd.h>
+#include "__dirent.h"
+#include "libc.h"
+
+void seekdir(DIR *dir, long off)
+{
+       LOCK(&dir->lock);
+       dir->tell = lseek(dir->fd, off, SEEK_SET);
+       dir->buf_pos = dir->buf_end = 0;
+       UNLOCK(&dir->lock);
+}
diff --git a/src/dirent/telldir.c b/src/dirent/telldir.c
new file mode 100644 (file)
index 0000000..cf25acf
--- /dev/null
@@ -0,0 +1,7 @@
+#include <dirent.h>
+#include "__dirent.h"
+
+long telldir(DIR *dir)
+{
+       return dir->tell;
+}
diff --git a/src/env/__environ.c b/src/env/__environ.c
new file mode 100644 (file)
index 0000000..d7bd5e5
--- /dev/null
@@ -0,0 +1,7 @@
+#include "libc.h"
+
+#undef environ
+char **___environ = 0;
+weak_alias(___environ, __environ);
+weak_alias(___environ, _environ);
+weak_alias(___environ, environ);
diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
new file mode 100644 (file)
index 0000000..70af77b
--- /dev/null
@@ -0,0 +1,26 @@
+#include "libc.h"
+
+/* Any use of __environ/environ will override this symbol. */
+char **__dummy_environ = (void *)-1;
+weak_alias(__dummy_environ, ___environ);
+
+int __libc_start_main(
+       int (*main)(int, char **, char **), int argc, char **argv,
+       int (*init)(int, char **, char **), void (*fini)(void),
+       void (*ldso_fini)(void))
+{
+       /* Save the environment if it may be used by libc/application */
+       char **envp = argv+argc+1;
+       if (___environ != (void *)-1) ___environ = envp;
+
+       /* Avoid writing 0 and triggering unnecessary COW */
+       if (ldso_fini) libc.ldso_fini = ldso_fini;
+       if (fini) libc.fini = fini;
+
+       /* Execute constructors (static) linked into the application */
+       if (init) init(argc, argv, envp);
+
+       /* Pass control to to application */
+       exit(main(argc, argv, envp));
+       return 0;
+}
diff --git a/src/env/clearenv.c b/src/env/clearenv.c
new file mode 100644 (file)
index 0000000..a2475ce
--- /dev/null
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+
+extern char **__environ;
+
+int clearenv()
+{
+       __environ[0] = 0;
+       return 0;
+}
diff --git a/src/env/getenv.c b/src/env/getenv.c
new file mode 100644 (file)
index 0000000..00c1bce
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <string.h>
+#include "libc.h"
+
+char *getenv(const char *name)
+{
+       int i;
+       size_t l = strlen(name);
+       if (!__environ || !*name || strchr(name, '=')) return NULL;
+       for (i=0; __environ[i] && (strncmp(name, __environ[i], l)
+               || __environ[i][l] != '='); i++);
+       if (__environ[i]) return __environ[i] + l+1;
+       return NULL;
+}
diff --git a/src/env/putenv.c b/src/env/putenv.c
new file mode 100644 (file)
index 0000000..181a418
--- /dev/null
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+extern char **__environ;
+char **__env_map;
+
+int __putenv(char *s, int a)
+{
+       int i=0, j=0;
+       char *end = strchr(s, '=');
+       size_t l = end-s+1;
+       char **newenv = 0;
+       char **newmap = 0;
+       static char **oldenv;
+       
+       if (!end || l == 1) return -1;
+       for (; __environ[i] && memcmp(s, __environ[i], l); i++);
+       if (a) {
+               if (!__env_map) {
+                       __env_map = calloc(2, sizeof(char *));
+                       if (__env_map) __env_map[0] = s;
+               } else {
+                       for (; __env_map[j] && __env_map[j] != __environ[i]; j++);
+                       if (!__env_map[j]) {
+                               newmap = realloc(__env_map, sizeof(char *)*(j+2));
+                               if (newmap) {
+                                       __env_map = newmap;
+                                       __env_map[j] = s;
+                                       __env_map[j+1] = NULL;
+                               }
+                       } else {
+                               free(__env_map[j]);
+                       }
+               }
+       }
+       if (!__environ[i]) {
+               newenv = malloc(sizeof(char *)*(i+2));
+               if (!newenv) {
+                       if (a && __env_map) __env_map[j] = 0;
+                       return -1;
+               }
+               memcpy(newenv, __environ, sizeof(char *)*i);
+               newenv[i] = s;
+               newenv[i+1] = 0;
+               __environ = newenv;
+               free(oldenv);
+               oldenv = __environ;
+       }
+
+       __environ[i] = s;
+       return 0;
+}
+
+int putenv(char *s)
+{
+       return __putenv(s, 0);
+}
diff --git a/src/env/setenv.c b/src/env/setenv.c
new file mode 100644 (file)
index 0000000..03e165c
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+int __putenv(char *s, int a);
+
+int setenv(const char *var, const char *value, int overwrite)
+{
+       char *s;
+       int l1, l2;
+
+       if (strchr(var, '=')) {
+               errno = EINVAL;
+               return -1;
+       }
+       if (!overwrite && getenv(var)) return 0;
+
+       l1 = strlen(var);
+       l2 = strlen(value);
+       s = malloc(l1+l2+2);
+       memcpy(s, var, l1);
+       s[l1] = '=';
+       memcpy(s+l1+1, value, l2);
+       s[l1+l2+1] = 0;
+       if (__putenv(s, 1)) {
+               free(s);
+               errno = ENOMEM;
+               return -1;
+       }
+       return 0;
+}
diff --git a/src/env/unsetenv.c b/src/env/unsetenv.c
new file mode 100644 (file)
index 0000000..7493d97
--- /dev/null
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+extern char **__environ;
+extern char **__env_map;
+
+int unsetenv(const char *name)
+{
+       int i, j;
+       size_t l = strlen(name);
+
+       if (!*name || strchr(name, '=')) {
+               errno = EINVAL;
+               return -1;
+       }
+again:
+       for (i=0; __environ[i] && (memcmp(name, __environ[i], l) || __environ[i][l] != '='); i++);
+       if (__environ[i]) {
+               if (__env_map) {
+                       for (j=0; __env_map[j] && __env_map[j] != __environ[i]; j++);
+                       free (__env_map[j]);
+                       for (; __env_map[j]; j++)
+                               __env_map[j] = __env_map[j+1];
+               }
+               for (; __environ[i]; i++)
+                       __environ[i] = __environ[i+1];
+               goto again;
+       }
+       return 0;
+}
diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c
new file mode 100644 (file)
index 0000000..0a220b6
--- /dev/null
@@ -0,0 +1,11 @@
+#include <errno.h>
+#include "libc.h"
+
+#undef errno
+int errno;
+
+int *__errno_location(void)
+{
+       if (libc.errno_location) return libc.errno_location();
+       return &errno;
+}
diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h
new file mode 100644 (file)
index 0000000..00eaf93
--- /dev/null
@@ -0,0 +1,101 @@
+/* This file is sorted such that 'errors' which represent exceptional
+ * conditions under which a correct program may fail come first, followed
+ * by messages that indicate an incorrect program or system failure. The
+ * macro E() along with double-inclusion is used to ensure that ordering
+ * of the strings remains synchronized. */
+
+E(EILSEQ,       "Illegal byte sequence")
+E(EDOM,         "Argument outside domain")
+E(ERANGE,       "Result not representable")
+
+E(ENOTTY,       "Not a tty")
+E(EACCES,       "Permission denied")
+E(EPERM,        "Operation not permitted")
+E(ENOENT,       "No such file or directory")
+E(ESRCH,        "No such process")
+E(EEXIST,       "File exists")
+
+E(EOVERFLOW,    "Value too large for defined data type")
+E(ENOSPC,       "No space left on device")
+E(ENOMEM,       "Out of memory")
+
+E(EBUSY,        "Device or resource busy")
+E(EINTR,        "Interrupted system call")
+E(EAGAIN,       "Operation would block")
+E(ESPIPE,       "Illegal seek")
+
+E(EXDEV,        "Cross-device link")
+E(EROFS,        "Read-only file system")
+E(ENOTEMPTY,    "Directory not empty")
+
+E(ECONNRESET,   "Connection reset by peer")
+E(ETIMEDOUT,    "Connection timed out")
+E(ECONNREFUSED, "Connection refused")
+E(EHOSTDOWN,    "Host is down")
+E(EHOSTUNREACH, "No route to host")
+E(EADDRINUSE,   "Address already in use")
+
+E(EPIPE,        "Broken pipe")
+E(EIO,          "I/O error")
+E(ENXIO,        "No such device or address")
+E(ENOTBLK,      "Block device required")
+E(ENODEV,       "No such device")
+E(ENOTDIR,      "Not a directory")
+E(EISDIR,       "Is a directory")
+E(ETXTBSY,      "Text file busy")
+E(ENOEXEC,      "Exec format error")
+
+E(EINVAL,       "Invalid argument")
+
+E(E2BIG,        "Argument list too long")
+E(ELOOP,        "Too many levels of symbolic links")
+E(ENAMETOOLONG, "Filename too long")
+E(ENFILE,       "File table overflow")
+E(EMFILE,       "Too many open files")
+E(EBADF,        "Bad file number")
+E(ECHILD,       "No child processes")
+E(EFAULT,       "Bad address")
+E(EFBIG,        "File too large")
+E(EMLINK,       "Too many links")
+E(ENOLCK,       "No record locks available")
+
+E(EDEADLK,      "Resource deadlock would occur")
+E(ENOSYS,       "Function not supported")
+E(ENOMSG,       "No message of desired type")
+E(EIDRM,        "Identifier removed")
+E(ENOSTR,       "Device not a stream")
+E(ENODATA,      "No data available")
+E(ETIME,        "Timer expired")
+E(ENOSR,        "Out of streams resources")
+E(ENOLINK,      "Link has been severed")
+E(EPROTO,       "Protocol error")
+E(EBADMSG,      "Not a data message")
+E(EBADFD,       "File descriptor in bad state")
+E(ENOTSOCK,     "Socket operation on non-socket")
+E(EDESTADDRREQ, "Destination address required")
+E(EMSGSIZE,     "Message too long")
+E(EPROTOTYPE,   "Protocol wrong type for socket")
+E(ENOPROTOOPT,  "Protocol not available")
+E(EPROTONOSUPPORT,"Protocol not supported")
+E(ESOCKTNOSUPPORT,"Socket type not supported")
+E(EOPNOTSUPP,   "Operation not supported on socket")
+E(EPFNOSUPPORT, "Protocol family not supported")
+E(EAFNOSUPPORT, "Address family not supported by protocol")
+E(EADDRNOTAVAIL,"Cannot assign requested address")
+E(ENETDOWN,     "Network is down")
+E(ENETUNREACH,  "Network is unreachable")
+E(ENETRESET,    "Network dropped connection because of reset")
+E(ECONNABORTED, "Software caused connection abort")
+E(ENOBUFS,      "No buffer space available")
+E(EISCONN,      "Socket is connected")
+E(ENOTCONN,     "Socket is not connected")
+E(ESHUTDOWN,    "Cannot send after socket shutdown")
+E(EALREADY,     "Operation already in progress")
+E(EINPROGRESS,  "Operation now in progress")
+E(ESTALE,       "Stale NFS file handle")
+E(EREMOTEIO,    "Remote I/O error")
+E(EDQUOT,       "Quota exceeded")
+E(ENOMEDIUM,    "No medium found")
+E(EMEDIUMTYPE,  "Wrong medium type")
+
+E(0,            "Invalid error number")
diff --git a/src/errno/strerror.c b/src/errno/strerror.c
new file mode 100644 (file)
index 0000000..b8fbc6d
--- /dev/null
@@ -0,0 +1,22 @@
+#include <errno.h>
+#include <string.h>
+
+#define E(a,b) a,
+static const unsigned char errid[] = {
+#include "__strerror.h"
+};
+
+#undef E
+#define E(a,b) b "\0"
+static const char errmsg[] =
+#include "__strerror.h"
+;
+
+char *strerror(int e)
+{
+       const char *s;
+       int i;
+       for (i=0; errid[i] && errid[i] != e; i++);
+       for (s=errmsg; i; s++, i--) for (; *s; s++);
+       return (char *)s;
+}
diff --git a/src/exit/_Exit.c b/src/exit/_Exit.c
new file mode 100644 (file)
index 0000000..8ef85a8
--- /dev/null
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+#define SYSCALL_NORETURN
+#include "syscall.h"
+
+void _Exit(int ec)
+{
+       syscall1(__NR_exit_group, ec);
+       syscall1(__NR_exit, ec);
+}
diff --git a/src/exit/abort.c b/src/exit/abort.c
new file mode 100644 (file)
index 0000000..9a1c3d4
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include <signal.h>
+
+void abort(void)
+{
+       raise(SIGABRT);
+       for (;;);
+}
diff --git a/src/exit/assert.c b/src/exit/assert.c
new file mode 100644 (file)
index 0000000..e87442a
--- /dev/null
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void __assert_fail(const char *expr, const char *file, int line, const char *func)
+{
+       fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
+       fflush(NULL);
+       abort();
+}
diff --git a/src/exit/atexit.c b/src/exit/atexit.c
new file mode 100644 (file)
index 0000000..49c060e
--- /dev/null
@@ -0,0 +1,57 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "libc.h"
+
+/* Ensure that at least 32 atexit handlers can be registered without malloc */
+#define COUNT 32
+
+static struct fl
+{
+       struct fl *next;
+       void (*f[COUNT])(void);
+} builtin, *head;
+
+static int run_atexit_functions(void)
+{
+       int i;
+       for (; head; head=head->next) {
+               for (i=COUNT-1; i>=0 && !head->f[i]; i--);
+               for (; i>=0; i--) head->f[i]();
+       }
+       return 0;
+}
+
+int (*const __funcs_on_exit)(void) = run_atexit_functions;
+
+int atexit(void (*func)(void))
+{
+       static int lock;
+       int i;
+
+       /* Hook for atexit extensions */
+       if (libc.atexit) return libc.atexit(func);
+
+       LOCK(&lock);
+
+       /* Defer initialization of head so it can be in BSS */
+       if (!head) head = &builtin;
+
+       /* If the current function list is full, add a new one */
+       if (head->f[COUNT-1]) {
+               struct fl *new_fl = calloc(sizeof(struct fl), 1);
+               if (!new_fl) {
+                       UNLOCK(&lock);
+                       return -1;
+               }
+               new_fl->next = head;
+               head = new_fl;
+       }
+
+       /* Append function to the list. */
+       for (i=0; i<COUNT && head->f[i]; i++);
+       head->f[i] = func;
+
+       UNLOCK(&lock);
+       return 0;
+}
diff --git a/src/exit/exit.c b/src/exit/exit.c
new file mode 100644 (file)
index 0000000..d0c1bfc
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "libc.h"
+
+/* __overflow.c and atexit.c override these */
+static int (*const dummy)() = 0;
+weak_alias(dummy, __funcs_on_exit);
+weak_alias(dummy, __fflush_on_exit);
+
+void exit(int code)
+{
+       static int lock;
+
+       /* If more than one thread calls exit, hang until _Exit ends it all */
+       LOCK(&lock);
+
+       /* Only do atexit & stdio flush if they were actually used */
+       if (__funcs_on_exit) __funcs_on_exit();
+       if (__fflush_on_exit) __fflush_on_exit(0);
+
+       /* Destructor s**t is kept separate from atexit to avoid bloat */
+       if (libc.fini) libc.fini();
+       if (libc.ldso_fini) libc.ldso_fini();
+
+       _Exit(code);
+       for(;;);
+}
diff --git a/src/fcntl/creat.c b/src/fcntl/creat.c
new file mode 100644 (file)
index 0000000..be05faa
--- /dev/null
@@ -0,0 +1,9 @@
+#include <fcntl.h>
+#include "libc.h"
+
+int creat(const char *filename, mode_t mode)
+{
+       return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode);
+}
+
+LFS64(creat);
diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c
new file mode 100644 (file)
index 0000000..464dbf0
--- /dev/null
@@ -0,0 +1,22 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include "syscall.h"
+#include "libc.h"
+
+int fcntl(int fd, int cmd, ...)
+{
+       int r;
+       long arg;
+       va_list ap;
+       va_start(ap, cmd);
+       arg = va_arg(ap, long);
+       va_end(ap);
+       if (cmd == F_SETFL) arg |= O_LARGEFILE;
+       if (cmd == F_SETLKW) CANCELPT_BEGIN;
+       r = __syscall_fcntl(fd, cmd, arg);
+       if (cmd == F_SETLKW) CANCELPT_END;
+       return r;
+}
+
+LFS64(fcntl);
diff --git a/src/fcntl/open.c b/src/fcntl/open.c
new file mode 100644 (file)
index 0000000..4c1a591
--- /dev/null
@@ -0,0 +1,21 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include "syscall.h"
+#include "libc.h"
+
+int open(const char *filename, int flags, ...)
+{
+       int r;
+       mode_t mode;
+       va_list ap;
+       va_start(ap, flags);
+       mode = va_arg(ap, mode_t);
+       va_end(ap);
+       CANCELPT_BEGIN;
+       r = __syscall_open(filename, flags, mode);
+       CANCELPT_END;
+       return r;
+}
+
+LFS64(open);
diff --git a/src/fcntl/openat.c b/src/fcntl/openat.c
new file mode 100644 (file)
index 0000000..eefa090
--- /dev/null
@@ -0,0 +1,21 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include "syscall.h"
+#include "libc.h"
+
+int openat(int fd, const char *filename, int flags, ...)
+{
+       int r;
+       mode_t mode;
+       va_list ap;
+       va_start(ap, flags);
+       mode = va_arg(ap, mode_t);
+       va_end(ap);
+       CANCELPT_BEGIN;
+       r = syscall4(__NR_openat, fd, (long)filename, flags|O_LARGEFILE, mode);
+       CANCELPT_END;
+       return r;
+}
+
+LFS64(openat);
diff --git a/src/internal/atomic.h b/src/internal/atomic.h
new file mode 100644 (file)
index 0000000..a15f8c2
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef _INTERNAA_ATOMIC_H
+#define _INTERNAA_ATOMIC_H
+
+#include <stdint.h>
+
+static inline int a_ctz_64(uint64_t x)
+{
+       int r;
+       __asm__( "bsf %1,%0 ; jnz 1f ; bsf %2,%0 ; addl $32,%0\n1:"
+               : "=r"(r) : "r"((unsigned)x), "r"((unsigned)(x>>32)) );
+       return r;
+}
+
+
+static inline void a_and_64(volatile uint64_t *p, uint64_t v)
+{
+       __asm__( "lock ; andl %1, (%0) ; lock ; andl %2, 4(%0)"
+               : : "r"((long *)p), "r"((unsigned)v), "r"((unsigned)(v>>32)) );
+}
+
+static inline void a_or_64(volatile uint64_t *p, uint64_t v)
+{
+       __asm__( "lock ; orl %1, (%0) ; lock ; orl %2, 4(%0)"
+               : : "r"((long *)p), "r"((unsigned)v), "r"((unsigned)(v>>32)) );
+}
+
+static inline void a_store_l(volatile void *p, long x)
+{
+       __asm__( "movl %1, %0" : "=m"(*(long *)p) : "r"(x) : "memory" );
+}
+
+static inline void a_or_l(volatile void *p, long v)
+{
+       __asm__( "lock ; orl %1, %0"
+               : "=m"(*(long *)p) : "r"(v) );
+}
+
+static inline void *a_cas_p(volatile void *p, void *t, void *s)
+{
+       __asm__( "lock ; cmpxchg %3, %1"
+               : "=a"(t), "=m"(*(long *)p) : "a"(t), "r"(s) );
+       return t;
+}
+
+static inline long a_cas_l(volatile void *p, long t, long s)
+{
+       __asm__( "lock ; cmpxchg %3, %1"
+               : "=a"(t), "=m"(*(long *)p) : "a"(t), "r"(s) );
+       return t;
+}
+
+static inline void *a_swap_p(void *volatile *x, void *v)
+{
+       __asm__( "xchg %0, %1" : "=r"(v), "=m"(*(void **)x) : "0"(v) );
+       return v;
+}
+static inline long a_swap_l(volatile void *x, long v)
+{
+       __asm__( "xchg %0, %1" : "=r"(v), "=m"(*(long *)x) : "0"(v) );
+       return v;
+}
+
+static inline void a_or(volatile void *p, int v)
+{
+       __asm__( "lock ; orl %1, %0"
+               : "=m"(*(int *)p) : "r"(v) );
+}
+
+static inline void a_and(volatile void *p, int v)
+{
+       __asm__( "lock ; andl %1, %0"
+               : "=m"(*(int *)p) : "r"(v) );
+}
+
+static inline int a_swap(volatile int *x, int v)
+{
+       __asm__( "xchg %0, %1" : "=r"(v), "=m"(*x) : "0"(v) );
+       return v;
+}
+
+#define a_xchg a_swap
+
+static inline int a_fetch_add(volatile int *x, int v)
+{
+       __asm__( "lock ; xadd %0, %1" : "=r"(v), "=m"(*x) : "0"(v) );
+       return v;
+}
+
+static inline void a_inc(volatile int *x)
+{
+       __asm__( "lock ; incl %0" : "=m"(*x) : "m"(*x) );
+}
+
+static inline void a_dec(volatile int *x)
+{
+       __asm__( "lock ; decl %0" : "=m"(*x) : "m"(*x) );
+}
+
+static inline void a_store(volatile int *p, int x)
+{
+       __asm__( "movl %1, %0" : "=m"(*p) : "r"(x) : "memory" );
+}
+
+static inline void a_spin()
+{
+       __asm__ __volatile__( "pause" : : : "memory" );
+}
+
+
+#endif
diff --git a/src/internal/clone.h b/src/internal/clone.h
new file mode 100644 (file)
index 0000000..cc84aeb
--- /dev/null
@@ -0,0 +1,22 @@
+#define CLONE_VM      0x00000100
+#define CLONE_FS      0x00000200
+#define CLONE_FILES   0x00000400
+#define CLONE_SIGHAND 0x00000800
+#define CLONE_PTRACE  0x00002000
+#define CLONE_VFORK   0x00004000
+#define CLONE_PARENT  0x00008000
+#define CLONE_THREAD  0x00010000
+#define CLONE_NEWNS   0x00020000
+#define CLONE_SYSVSEM 0x00040000
+#define CLONE_SETTLS  0x00080000
+#define CLONE_PARENT_SETTID 0x00100000
+#define CLONE_CHILD_CLEARTID 0x00200000
+#define CLONE_DETACHED 0x00400000
+#define CLONE_UNTRACED 0x00800000
+#define CLONE_CHILD_SETTID 0x01000000
+#define CLONE_NEWUTS   0x04000000
+#define CLONE_NEWIPC   0x08000000
+#define CLONE_NEWUSER  0x10000000
+#define CLONE_NEWPID   0x20000000
+#define CLONE_NEWNET   0x40000000
+#define CLONE_IO       0x80000000
diff --git a/src/internal/futex.h b/src/internal/futex.h
new file mode 100644 (file)
index 0000000..c045382
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _INTERNAL_FUTEX_H
+#define _INTERNAL_FUTEX_H
+
+#define FUTEX_WAIT             0
+#define FUTEX_WAKE             1
+#define FUTEX_FD               2
+#define FUTEX_REQUEUE          3
+#define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_LOCK_PI          6
+#define FUTEX_UNLOCK_PI                7
+#define FUTEX_TRYLOCK_PI       8
+
+int __futex(volatile int *, int, int, void *);
+
+#endif
diff --git a/src/internal/libc.c b/src/internal/libc.c
new file mode 100644 (file)
index 0000000..5e8e9d9
--- /dev/null
@@ -0,0 +1,3 @@
+#include "libc.h"
+
+struct libc libc;
diff --git a/src/internal/libc.h b/src/internal/libc.h
new file mode 100644 (file)
index 0000000..e353f36
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef LIBC_H
+#define LIBC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define libc __libc
+extern struct libc {
+       void (*lock)(volatile int *);
+       void (*cancelpt)(int);
+       int (*atexit)(void (*)(void));
+       void (*fini)(void);
+       void (*ldso_fini)(void);
+       int *(*errno_location)(void);
+       volatile int threads_minus_1;
+       int (*rsyscall)(int, long, long, long, long, long, long);
+       void (**tsd_keys)(void *);
+} libc;
+
+
+/* Designed to avoid any overhead in non-threaded processes */
+void __lock(volatile int *);
+#define LOCK(x) (libc.threads_minus_1 ? (__lock(x),1) : ((void)(x),1))
+#define UNLOCK(x) (*(x)=0)
+#define CANCELPT(x) (libc.cancelpt ? libc.cancelpt((x)),0 : (void)(x),0)
+#define CANCELPT_BEGIN CANCELPT(1)
+#define CANCELPT_END CANCELPT(0)
+
+extern char **__environ;
+#define environ __environ
+
+#undef weak_alias
+#define weak_alias(old, new) \
+       extern __typeof(old) new __attribute__((weak, alias(#old)))
+
+#undef LFS64_2
+//#define LFS64_2(x, y) weak_alias(x, y)
+#define LFS64_2(x, y) extern __typeof(x) y
+
+#undef LFS64
+#define LFS64(x) LFS64_2(x, x##64)
+
+#endif
diff --git a/src/internal/locale_impl.h b/src/internal/locale_impl.h
new file mode 100644 (file)
index 0000000..c268124
--- /dev/null
@@ -0,0 +1,5 @@
+#include <locale.h>
+
+struct __locale {
+       int dummy;
+};
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
new file mode 100644 (file)
index 0000000..b789210
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef _PTHREAD_IMPL_H
+#define _PTHREAD_IMPL_H
+
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <string.h>
+#include <time.h>
+#include "libc.h"
+#include "syscall.h"
+#include "atomic.h"
+#include "futex.h"
+
+#define pthread __pthread
+
+struct pthread {
+       struct pthread *self, *join;
+       int errno_val;
+       pid_t tid, pid;
+       volatile int canceldisable, cancelasync, cancelpoint, cancel;
+       unsigned char *map_base;
+       size_t map_size;
+       void *start_arg;
+       void *(*start)(void *);
+       void *result;
+       jmp_buf exit_jmp_buf;
+       int detached;
+       int exitlock;
+       unsigned long tlsdesc[4];
+       struct __ptcb *cancelbuf;
+       void **tsd;
+       int tsd_used;
+       pthread_attr_t attr;
+       int *errno_ptr;
+};
+
+static inline struct pthread *__pthread_self()
+{
+       struct pthread *self;
+       __asm__ ("movl %%gs:0,%0" : "=r" (self) );
+       return self;
+}
+
+#define SIGCANCEL 32
+#define SIGSYSCALL 33
+#define SIGTIMER  32 /* ?? */
+
+int __set_thread_area(unsigned long *);
+int __set_pthread_self(void *);
+int __libc_sigaction(int, const struct sigaction *, struct sigaction *);
+int __libc_sigprocmask(int, const sigset_t *, sigset_t *);
+void __lock(volatile int *);
+void __unmapself(void *, size_t);
+
+int __timedwait(volatile int *, int, clockid_t, const struct timespec *, int);
+void __wait(volatile int *, volatile int *, int, int);
+void __wake(volatile int *, int, int);
+
+#define DEFAULT_STACK_SIZE (16384-PAGE_SIZE)
+#define DEFAULT_GUARD_SIZE PAGE_SIZE
+
+#endif
diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h
new file mode 100644 (file)
index 0000000..1e9159f
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef _STDIO_IMPL_H
+#define _STDIO_IMPL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <math.h>
+#include <float.h>
+#include "syscall.h"
+#include "libc.h"
+
+#define UNGET 4
+
+#define FLOCK(f) LOCK(&f->lock)
+#define FUNLOCK(f) UNLOCK(&f->lock)
+
+#define F_PERM 1
+#define F_NORD 4
+#define F_NOWR 8
+#define F_EOF 16
+#define F_ERR 32
+
+struct __FILE_s {
+       unsigned flags;
+       unsigned char *rpos, *rstop;
+       unsigned char *rend, *wend;
+       unsigned char *wpos, *wstop;
+       unsigned char *wbase;
+       unsigned char *dummy01[3];
+       unsigned char *buf;
+       size_t buf_size;
+       FILE *prev, *next;
+       int fd;
+       int pipe_pid;
+       long dummy2;
+       short dummy3;
+       char dummy4;
+       signed char lbf;
+       int lock;
+       int lockcount;
+       void *owner;
+       off_t off;
+       int (*flush)(FILE *);
+       void **wide_data; /* must be NULL */
+       size_t (*read)(FILE *, unsigned char *, size_t);
+       size_t (*write)(FILE *, const unsigned char *, size_t);
+       off_t (*seek)(FILE *, off_t, int);
+       int mode;
+       int (*close)(FILE *);
+};
+
+size_t __stdio_read(FILE *, unsigned char *, size_t);
+size_t __stdio_write(FILE *, const unsigned char *, size_t);
+off_t __stdio_seek(FILE *, off_t, int);
+int __stdio_close(FILE *);
+
+int __overflow(FILE *, int);
+int __oflow(FILE *);
+int __uflow(FILE *);
+int __underflow(FILE *);
+
+int __fseeko(FILE *, off_t, int);
+int __fseeko_unlocked(FILE *, off_t, int);
+off_t __ftello(FILE *);
+off_t __ftello_unlocked(FILE *);
+size_t __fwritex(const unsigned char *, size_t, FILE *);
+int __putc_unlocked(int, FILE *);
+
+FILE *__fdopen(int, const char *);
+
+extern struct ofl
+{
+       FILE *head;
+       int lock;
+} __ofl;
+
+#define OFLLOCK() LOCK(&__ofl.lock)
+#define OFLUNLOCK() UNLOCK(&__ofl.lock)
+#define ofl_head (__ofl.head)
+
+#define feof(f) ((f)->flags & F_EOF)
+#define ferror(f) ((f)->flags & F_ERR)
+
+/* Caller-allocated FILE * operations */
+FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t);
+int __fclose_ca(FILE *);
+
+#endif
diff --git a/src/internal/syscall.c b/src/internal/syscall.c
new file mode 100644 (file)
index 0000000..4f159e0
--- /dev/null
@@ -0,0 +1,11 @@
+#include <errno.h>
+#include <unistd.h>
+
+long __syscall_ret(unsigned long r)
+{
+       if (r >= (unsigned long)-1 - 4096) {
+               errno = -(long)r;
+               return -1;
+       }
+       return (long)r;
+}
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
new file mode 100644 (file)
index 0000000..4b3c0a7
--- /dev/null
@@ -0,0 +1,469 @@
+#ifndef _SYSCALL_H
+#define _SYSCALL_H
+
+#define SYSCALL_LL(x) \
+((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
+((union { long long ll; long l[2]; }){ .ll = x }).l[1]
+
+#define SYSCALL_SIGSET_SIZE 8
+
+#if defined(SYSCALL_STANDALONE)
+#include <errno.h>
+static inline long __syscall_ret(unsigned long r)
+{
+       if (r >= (unsigned long)-1 - 4096) {
+               errno = -(long)r;
+               return -1;
+       }
+       return (long)r;
+}
+#elif defined(SYSCALL_NORETURN)
+static inline long __syscall_ret(unsigned long r)
+{
+       for(;;);
+       return 0;
+}
+#elif defined(SYSCALL_RETURN_ERRNO)
+static inline long __syscall_ret(unsigned long r)
+{
+       return -r;
+}
+#else
+extern long __syscall_ret(unsigned long);
+#endif
+
+#define SYSCALL0 "int $128"
+
+#ifdef __PIC__
+#define SYSCALL "xchgl %%ebx,%2\n\t" SYSCALL0 "\n\txchgl %%ebx,%2"
+#define EBX "m"
+#else
+#define SYSCALL SYSCALL0
+#define EBX "b"
+#endif
+
+static inline long syscall0(long n)
+{
+       unsigned long ret;
+       __asm__ __volatile__ (SYSCALL0 : "=a"(ret) : "a"(n) : "memory");
+       return __syscall_ret(ret);
+}
+
+static inline long syscall1(long n, long a1)
+{
+       unsigned long ret;
+       __asm__ __volatile__ (SYSCALL : "=a"(ret) : "a"(n), EBX(a1) : "memory");
+       return __syscall_ret(ret);
+}
+
+static inline long syscall2(long n, long a1, long a2)
+{
+       unsigned long ret;
+       __asm__ __volatile__ (SYSCALL : "=a"(ret) : "a"(n), EBX(a1), "c"(a2) : "memory");
+       return __syscall_ret(ret);
+}
+
+static inline long syscall3(long n, long a1, long a2, long a3)
+{
+       unsigned long ret;
+       __asm__ __volatile__ (SYSCALL : "=a"(ret) : "a"(n), EBX(a1), "c"(a2), "d"(a3) : "memory");
+       return __syscall_ret(ret);
+}
+
+static inline long syscall4(long n, long a1, long a2, long a3, long a4)
+{
+       unsigned long ret;
+       __asm__ __volatile__ (SYSCALL : "=a"(ret) : "a"(n), EBX(a1), "c"(a2), "d"(a3), "S"(a4) : "memory");
+       return __syscall_ret(ret);
+}
+
+static inline long syscall5(long n, long a1, long a2, long a3, long a4, long a5)
+{
+       unsigned long ret;
+       __asm__ __volatile__ (SYSCALL : "=a"(ret) : "a"(n), EBX(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory");
+       return __syscall_ret(ret);
+}
+
+#ifdef __PIC__
+/* note: it's probably only safe to use this when a6 is on the stack */
+static inline long syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6)
+{
+       unsigned long ret;
+       __asm__ __volatile__ ("xchgl %%ebx,%2 ; pushl %1 ; pushl %%ebp ; movl %%eax,%%ebp ; movl 4(%%esp),%%eax ; int $128 ; popl %%ebp ; popl %%ecx ; xchgl %%ebx,%2"
+               : "=a"(ret) : "g"(n), EBX(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5), "a"(a6) : "memory");
+       return __syscall_ret(ret);
+}
+#else
+static inline long syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6)
+{
+       unsigned long ret;
+       __asm__ __volatile__ ("pushl %%ebp ; mov %1, %%ebp ; xchg %%ebp, %7 ; int $128 ; popl %%ebp"
+               : "=a"(ret) : "g"(n), EBX(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5), "a"(a6) : "memory");
+       return __syscall_ret(ret);
+}
+#endif
+
+#define __NR_restart_syscall      0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_lchown             16
+#define __NR_break              17
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+#define __NR_stty               31
+#define __NR_gtty               32
+#define __NR_access             33
+#define __NR_nice               34
+#define __NR_ftime              35
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+#define __NR_prof               44
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+#define __NR_lock               53
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+#define __NR_mpx                56
+#define __NR_setpgid            57
+#define __NR_ulimit             58
+#define __NR_oldolduname        59
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76   /* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+#define __NR_profil             98
+#define __NR_statfs            99
+#define __NR_fstatfs           100
+#define __NR_ioperm            101
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+#define __NR_olduname          109
+#define __NR_iopl              110
+#define __NR_vhangup           111
+#define __NR_idle              112
+#define __NR_vm86old           113
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_modify_ldt                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+#define __NR_afs_syscall       137
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_vm86              166
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_chown             182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188
+#define __NR_putpmsg           189
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_lchown32          198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+#define __NR_mincore           218
+#define __NR_madvise           219
+#define __NR_madvise1          219
+#define __NR_getdents64                220
+#define __NR_fcntl64           221
+/* 223 is unused */
+#define __NR_gettid            224
+#define __NR_readahead         225
+#define __NR_setxattr          226
+#define __NR_lsetxattr         227
+#define __NR_fsetxattr         228
+#define __NR_getxattr          229
+#define __NR_lgetxattr         230
+#define __NR_fgetxattr         231
+#define __NR_listxattr         232
+#define __NR_llistxattr                233
+#define __NR_flistxattr                234
+#define __NR_removexattr       235
+#define __NR_lremovexattr      236
+#define __NR_fremovexattr      237
+#define __NR_tkill             238
+#define __NR_sendfile64                239
+#define __NR_futex             240
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+#define __NR_set_thread_area   243
+#define __NR_get_thread_area   244
+#define __NR_io_setup          245
+#define __NR_io_destroy                246
+#define __NR_io_getevents      247
+#define __NR_io_submit         248
+#define __NR_io_cancel         249
+#define __NR_fadvise64         250
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_exit_group                252
+#define __NR_lookup_dcookie    253
+#define __NR_epoll_create      254
+#define __NR_epoll_ctl         255
+#define __NR_epoll_wait                256
+#define __NR_remap_file_pages  257
+#define __NR_set_tid_address   258
+#define __NR_timer_create      259
+#define __NR_timer_settime     (__NR_timer_create+1)
+#define __NR_timer_gettime     (__NR_timer_create+2)
+#define __NR_timer_getoverrun  (__NR_timer_create+3)
+#define __NR_timer_delete      (__NR_timer_create+4)
+#define __NR_clock_settime     (__NR_timer_create+5)
+#define __NR_clock_gettime     (__NR_timer_create+6)
+#define __NR_clock_getres      (__NR_timer_create+7)
+#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_statfs64          268
+#define __NR_fstatfs64         269
+#define __NR_tgkill            270
+#define __NR_utimes            271
+#define __NR_fadvise64_64      272
+#define __NR_vserver           273
+#define __NR_mbind             274
+#define __NR_get_mempolicy     275
+#define __NR_set_mempolicy     276
+#define __NR_mq_open           277
+#define __NR_mq_unlink         (__NR_mq_open+1)
+#define __NR_mq_timedsend      (__NR_mq_open+2)
+#define __NR_mq_timedreceive   (__NR_mq_open+3)
+#define __NR_mq_notify         (__NR_mq_open+4)
+#define __NR_mq_getsetattr     (__NR_mq_open+5)
+#define __NR_kexec_load                283
+#define __NR_waitid            284
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_add_key           286
+#define __NR_request_key       287
+#define __NR_keyctl            288
+#define __NR_ioprio_set                289
+#define __NR_ioprio_get                290
+#define __NR_inotify_init      291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch  293
+#define __NR_migrate_pages     294
+#define __NR_openat            295
+#define __NR_mkdirat           296
+#define __NR_mknodat           297
+#define __NR_fchownat          298
+#define __NR_futimesat         299
+#define __NR_fstatat64         300
+#define __NR_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#define __NR_faccessat         307
+#define __NR_pselect6          308
+#define __NR_ppoll             309
+#define __NR_unshare           310
+#define __NR_set_robust_list   311
+#define __NR_get_robust_list   312
+#define __NR_splice            313
+#define __NR_sync_file_range   314
+#define __NR_tee               315
+#define __NR_vmsplice          316
+#define __NR_move_pages                317
+#define __NR_getcpu            318
+#define __NR_epoll_pwait       319
+#define __NR_utimensat         320
+#define __NR_signalfd          321
+#define __NR_timerfd_create    322
+#define __NR_eventfd           323
+#define __NR_fallocate         324
+#define __NR_timerfd_settime   325
+#define __NR_timerfd_gettime   326
+#define __NR_signalfd4         327
+#define __NR_eventfd2          328
+#define __NR_epoll_create1     329
+#define __NR_dup3              330
+#define __NR_pipe2             331
+#define __NR_inotify_init1     332
+#define __NR_preadv            333
+#define __NR_pwritev           334
+
+
+#undef O_LARGEFILE
+#define O_LARGEFILE 0100000
+
+/* the following are needed for iso c functions to use */
+#define __syscall_open(filename, flags, mode) syscall3(__NR_open, (long)(filename), (flags)|O_LARGEFILE, (mode))
+#define __syscall_read(fd, buf, len)          syscall3(__NR_read, (fd), (long)(buf), (len))
+#define __syscall_write(fd, buf, len)         syscall3(__NR_write, (fd), (long)(buf), (len))
+#define __syscall_close(fd)                   syscall1(__NR_close, (fd))
+#define __syscall_fcntl(fd, cmd, arg)         syscall3(__NR_fcntl64, (fd), (cmd), (long)(arg))
+#define __syscall_dup2(old, new)              syscall2(__NR_dup2, (old), (new))
+#define __syscall_unlink(path)                syscall1(__NR_unlink, (long)(path))
+#define __syscall_getpid()                    syscall0(__NR_getpid)
+#define __syscall_kill(pid,sig)               syscall2(__NR_kill, (pid), (sig))
+#define __syscall_sigaction(sig,new,old)      syscall4(__NR_rt_sigaction, (sig), (long)(new), (long)(old), SYSCALL_SIGSET_SIZE)
+#define __syscall_ioctl(fd,ioc,arg)           syscall3(__NR_ioctl, (fd), (ioc), (long)(arg))
+#define __syscall_exit(code)                  syscall1(__NR_exit, code)
+
+#define __NEED_off_t
+#include <bits/alltypes.h>
+
+static inline off_t __syscall_lseek(int fd, off_t offset, int whence)
+{
+       off_t result;
+       return syscall5(__NR__llseek, fd, offset>>32, offset, (long)&result, whence) ? -1 : result;
+}
+
+#endif
diff --git a/src/internal/util.h b/src/internal/util.h
new file mode 100644 (file)
index 0000000..7c7c3a1
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef _INTERNAL_UTIL_H
+#define _INTERNAL_UTIL_H
+
+
+#endif
diff --git a/src/ipc/ftok.c b/src/ipc/ftok.c
new file mode 100644 (file)
index 0000000..cd6002e
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/ipc.h>
+#include <sys/stat.h>
+
+key_t ftok(const char *path, int id)
+{
+       struct stat st;
+       if (stat(path, &st) < 0) return -1;
+
+       return ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | ((id & 0xff) << 24));
+}
diff --git a/src/ipc/ipc.h b/src/ipc/ipc.h
new file mode 100644 (file)
index 0000000..9edd5ec
--- /dev/null
@@ -0,0 +1,13 @@
+#define IPCOP_semop      1
+#define IPCOP_semget     2
+#define IPCOP_semctl     3
+#define IPCOP_msgsnd    11
+#define IPCOP_msgrcv    12
+#define IPCOP_msgget    13
+#define IPCOP_msgctl    14
+#define IPCOP_shmat     21
+#define IPCOP_shmdt     22
+#define IPCOP_shmget    23
+#define IPCOP_shmctl    24
+
+#define IPC_MODERN   0x100
diff --git a/src/ipc/semctl.c b/src/ipc/semctl.c
new file mode 100644 (file)
index 0000000..7ada116
--- /dev/null
@@ -0,0 +1,18 @@
+#include <sys/sem.h>
+#include <stdarg.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int semctl(int id, int num, int cmd, ...)
+{
+       long arg;
+       va_list ap;
+       va_start(ap, cmd);
+       arg = va_arg(ap, long);
+       va_end(ap);
+#ifdef __NR_semctl
+       return syscall4(__NR_semctl, id, num, cmd, arg);
+#else
+       return syscall5(__NR_ipc, IPCOP_semctl, id, num, cmd | 0x100, (long)&arg);
+#endif
+}
diff --git a/src/ipc/semget.c b/src/ipc/semget.c
new file mode 100644 (file)
index 0000000..2dcf6ea
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/sem.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int semget(key_t key, int n, int fl)
+{
+#ifdef __NR_semget
+       return syscall3(__NR_semget, key, n, fl);
+#else
+       return syscall4(__NR_ipc, IPCOP_semget, key, n, fl);
+#endif
+}
diff --git a/src/ipc/semop.c b/src/ipc/semop.c
new file mode 100644 (file)
index 0000000..48d8a65
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/sem.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int semop(int id, struct sembuf *buf, size_t n)
+{
+#ifdef __NR_semop
+       return syscall3(__NR_semop, id, (long)buf, n);
+#else
+       return syscall5(__NR_ipc, IPCOP_semop, id, n, 0, (long)buf);
+#endif
+}
diff --git a/src/ipc/shmat.c b/src/ipc/shmat.c
new file mode 100644 (file)
index 0000000..ff65b6a
--- /dev/null
@@ -0,0 +1,17 @@
+#include <sys/shm.h>
+#include "syscall.h"
+#include "ipc.h"
+
+#ifdef __NR_shmat
+void *shmat(int id, const void *addr, int flag)
+{
+       return syscall3(__NR_shmat, id, (long)addr, flag);
+}
+#else
+void *shmat(int id, const void *addr, int flag)
+{
+       unsigned long ret;
+       ret = syscall5(__NR_ipc, IPCOP_shmat, id, flag, (long)&addr, (long)addr);
+       return (ret > -(unsigned long)SHMLBA) ? (void *)ret : (void *)addr;
+}
+#endif
diff --git a/src/ipc/shmctl.c b/src/ipc/shmctl.c
new file mode 100644 (file)
index 0000000..da357fa
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/shm.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int shmctl(int id, int cmd, struct shmid_ds *buf)
+{
+#ifdef __NR_shmctl
+       return syscall3(__NR_shmctl, id, cmd, (long)buf);
+#else
+       return syscall4(__NR_ipc, IPCOP_shmctl, id, cmd | IPC_MODERN, (long)buf);
+#endif
+}
diff --git a/src/ipc/shmdt.c b/src/ipc/shmdt.c
new file mode 100644 (file)
index 0000000..e04188f
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/shm.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int shmdt(const void *addr)
+{
+#ifdef __NR_shmdt
+       return syscall1(__NR_shmdt, (long)addr);
+#else
+       return syscall2(__NR_ipc, IPCOP_shmdt, (long)addr);
+#endif
+}
diff --git a/src/ipc/shmget.c b/src/ipc/shmget.c
new file mode 100644 (file)
index 0000000..86e254a
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/shm.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int shmget(key_t key, size_t size, int flag)
+{
+#ifdef __NR_shmget
+       return syscall3(__NR_shmget, key, size, flag);
+#else
+       return syscall4(__NR_ipc, IPCOP_shmget, key, size, flag);
+#endif
+}
diff --git a/src/linux/brk.c b/src/linux/brk.c
new file mode 100644 (file)
index 0000000..3c2982c
--- /dev/null
@@ -0,0 +1,6 @@
+#include "syscall.h"
+
+int brk(void *end)
+{
+       return -(syscall1(__NR_brk, (long)end) == -1);
+}
diff --git a/src/linux/chroot.c b/src/linux/chroot.c
new file mode 100644 (file)
index 0000000..b5af62d
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int chroot(const char *path)
+{
+       return syscall1(__NR_chroot, (long)path);
+}
diff --git a/src/linux/daemon.c b/src/linux/daemon.c
new file mode 100644 (file)
index 0000000..632d120
--- /dev/null
@@ -0,0 +1,31 @@
+#include <fcntl.h>
+#include <unistd.h>
+
+int daemon(int nochdir, int noclose)
+{
+       int fd;
+
+       switch(fork()) {
+       case 0: break;
+       case -1: return -1;
+       default: _exit(0);
+       }
+
+       if (setsid() < 0) return -1;
+
+       switch(fork()) {
+       case 0: break;
+       case -1: return -1;
+       default: _exit(0);
+       }
+
+       if (!nochdir) chdir("/");
+       if (!noclose && (fd = open("/dev/null", O_RDWR)) >= 0) {
+               dup2(fd, 0);
+               dup2(fd, 1);
+               dup2(fd, 2);
+               if (fd > 2) close(fd);
+       }
+
+       return 0;
+}
diff --git a/src/linux/epoll_create.c b/src/linux/epoll_create.c
new file mode 100644 (file)
index 0000000..c9dea8c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/epoll.h>
+#include "syscall.h"
+
+int epoll_create(int size)
+{
+       return syscall1(__NR_epoll_create, size);
+}
diff --git a/src/linux/epoll_create1.c b/src/linux/epoll_create1.c
new file mode 100644 (file)
index 0000000..2e82e99
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/epoll.h>
+#include "syscall.h"
+
+int epoll_create1(int flags)
+{
+       return syscall1(__NR_epoll_create1, flags);
+}
diff --git a/src/linux/epoll_ctl.c b/src/linux/epoll_ctl.c
new file mode 100644 (file)
index 0000000..4214f40
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/epoll.h>
+#include "syscall.h"
+
+int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
+{
+       return syscall4(__NR_epoll_ctl, fd, op, fd2, (long)ev);
+}
diff --git a/src/linux/epoll_pwait.c b/src/linux/epoll_pwait.c
new file mode 100644 (file)
index 0000000..5aaacba
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/epoll.h>
+#include "syscall.h"
+
+int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs)
+{
+       return syscall6(__NR_epoll_pwait, fd, (long)ev, cnt, to, (long)sigs, 8);
+}
diff --git a/src/linux/epoll_wait.c b/src/linux/epoll_wait.c
new file mode 100644 (file)
index 0000000..8a68ebd
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/epoll.h>
+#include "syscall.h"
+
+int epoll_wait(int fd, struct epoll_event *ev, int cnt, int to)
+{
+       return syscall4(__NR_epoll_wait, fd, (long)ev, cnt, to);
+}
diff --git a/src/linux/getdtablesize.c b/src/linux/getdtablesize.c
new file mode 100644 (file)
index 0000000..623a6af
--- /dev/null
@@ -0,0 +1,9 @@
+#include <limits.h>
+#include <sys/resource.h>
+
+int getdtablesize(void)
+{
+       struct rlimit rl;
+       getrlimit(RLIMIT_NOFILE, &rl);
+       return rl.rlim_max < INT_MAX ? rl.rlim_max : INT_MAX;
+}
diff --git a/src/linux/gethostid.c b/src/linux/gethostid.c
new file mode 100644 (file)
index 0000000..ea65611
--- /dev/null
@@ -0,0 +1,4 @@
+long gethostid()
+{
+       return 0;
+}
diff --git a/src/linux/getopt_long.c b/src/linux/getopt_long.c
new file mode 100644 (file)
index 0000000..d80cd1b
--- /dev/null
@@ -0,0 +1,52 @@
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <getopt.h>
+#include <stdio.h>
+
+static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
+{
+       if (optind >= argc || !argv[optind] || argv[optind][0] != '-') return -1;
+       if ((longonly && argv[optind][1]) ||
+               (argv[optind][1] == '-' && argv[optind][2]))
+       {
+               int i;
+               for (i=0; longopts[i].name; i++) {
+                       const char *name = longopts[i].name;
+                       char *opt = argv[optind]+1;
+                       if (*opt == '-') opt++;
+                       while (*name && *name++ == *opt++);
+                       if (*name || (*opt && *opt != '=')) continue;
+                       if (*opt == '=') {
+                               if (!longopts[i].has_arg) continue;
+                               optarg = opt+1;
+                       } else {
+                               if (longopts[i].has_arg == required_argument) {
+                                       if (!(optarg = argv[++optind]))
+                                               return ':';
+                               } else optarg = NULL;
+                       }
+                       optind++;
+                       if (idx) *idx = i;
+                       if (longopts[i].flag) {
+                               *longopts[i].flag = longopts[i].val;
+                               return 0;
+                       }
+                       return longopts[i].val;
+               }
+               if (argv[optind][1] == '-') {
+                       optind++;
+                       return '?';
+               }
+       }
+       return getopt(argc, argv, optstring);
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
+{
+       return __getopt_long(argc, argv, optstring, longopts, idx, 0);
+}
+
+int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
+{
+       return __getopt_long(argc, argv, optstring, longopts, idx, 1);
+}
diff --git a/src/linux/getpagesize.c b/src/linux/getpagesize.c
new file mode 100644 (file)
index 0000000..5ede652
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <limits.h>
+
+int getpagesize(void)
+{
+       return PAGE_SIZE;
+}
diff --git a/src/linux/getpass.c b/src/linux/getpass.c
new file mode 100644 (file)
index 0000000..d439a2a
--- /dev/null
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+char *getpass(const char *prompt)
+{
+       int fd;
+       struct termios s, t;
+       ssize_t l;
+       static char password[128];
+
+       if ((fd = open("/dev/tty", O_RDONLY|O_NOCTTY)) < 0) fd = 0;
+
+       tcgetattr(fd, &t);
+       s = t;
+       t.c_lflag &= ~(ECHO|ISIG);
+       t.c_lflag |= ICANON;
+       t.c_iflag &= ~(INLCR|IGNCR);
+       t.c_iflag |= ICRNL;
+       tcsetattr(fd, TCSAFLUSH, &t);
+       tcdrain(fd);
+
+       fputs(prompt, stderr);
+       fflush(stderr);
+
+       l = read(fd, password, sizeof password);
+       if (l >= 0) {
+               if (l > 0 && password[l-1] == '\n') l--;
+               password[l] = 0;
+       }
+
+       tcsetattr(fd, TCSAFLUSH, &s);
+
+       if (fd > 2) close(fd);
+
+       return password;
+}
diff --git a/src/linux/initgroups.c b/src/linux/initgroups.c
new file mode 100644 (file)
index 0000000..ef9bc10
--- /dev/null
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <grp.h>
+#include <limits.h>
+
+int getgrouplist(const char *, gid_t, gid_t *, int *);
+int setgroups(size_t, const gid_t *);
+
+int initgroups(const char *user, gid_t gid)
+{
+       gid_t groups[NGROUPS_MAX];
+       int count;
+       if (getgrouplist(user, gid, groups, &count) < 0) return -1;
+       return setgroups(count, groups);
+}
diff --git a/src/linux/klogctl.c b/src/linux/klogctl.c
new file mode 100644 (file)
index 0000000..6c288af
--- /dev/null
@@ -0,0 +1,7 @@
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int klogctl (int type, char *buf, int len)
+{
+       return syscall3(__NR_syslog, type, (long)buf, len);
+}
diff --git a/src/linux/mntent.c b/src/linux/mntent.c
new file mode 100644 (file)
index 0000000..e373566
--- /dev/null
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <string.h>
+#include <mntent.h>
+
+FILE *setmntent(const char *name, const char *mode)
+{
+       return fopen(name, mode);
+}
+
+int endmntent(FILE *f)
+{
+       fclose(f);
+       return 1;
+}
+
+struct mntent *getmntent(FILE *f)
+{
+       static char linebuf[256];
+       static struct mntent mnt;
+       int cnt, n[8];
+
+       mnt.mnt_freq = 0;
+       mnt.mnt_passno = 0;
+
+       do {
+               fgets(linebuf, sizeof linebuf, f);
+               if (feof(f)) return NULL;
+               cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
+                       n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
+                       &mnt.mnt_freq, &mnt.mnt_passno);
+       } while (cnt >= 8 && linebuf[n[0]] != '#');
+
+       linebuf[n[1]] = 0;
+       linebuf[n[3]] = 0;
+       linebuf[n[5]] = 0;
+       linebuf[n[7]] = 0;
+
+       mnt.mnt_fsname = linebuf+n[0];
+       mnt.mnt_dir = linebuf+n[2];
+       mnt.mnt_type = linebuf+n[4];
+       mnt.mnt_opts = linebuf+n[6];
+
+       return &mnt;
+}
+
+int addmntent(FILE *f, const struct mntent *mnt)
+{
+       fseek(f, 0, SEEK_END);
+       return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n",
+               mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts,
+               mnt->mnt_freq, mnt->mnt_passno) < 0;
+}
+
+char *hasmntopt(const struct mntent *mnt, const char *opt)
+{
+       return strstr(mnt->mnt_opts, opt);
+}
diff --git a/src/linux/mount.c b/src/linux/mount.c
new file mode 100644 (file)
index 0000000..61299d4
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/mount.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int mount(const char *special, const char *dir, const char *fstype, unsigned long flags, const void *data)
+{
+       return syscall5(__NR_mount, (long)special, (long)dir, (long)fstype, flags, (long)data);
+}
diff --git a/src/linux/prctl.c b/src/linux/prctl.c
new file mode 100644 (file)
index 0000000..d551683
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/prctl.h>
+#include <stdarg.h>
+#include "syscall.h"
+
+int prctl(int op, ...)
+{
+       unsigned long x[4];
+       int i;
+       va_list ap;
+       va_start(ap, op);
+       for (i=0; i<4; i++) x[i] = va_arg(ap, unsigned long);
+       return syscall5(__NR_prctl, op, x[0], x[1], x[2], x[3]);
+}
diff --git a/src/linux/reboot.c b/src/linux/reboot.c
new file mode 100644 (file)
index 0000000..68830d8
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/reboot.h>
+#include <errno.h>
+
+int reboot(int type)
+{
+       errno = ENOSYS;
+       return -1;
+}
diff --git a/src/linux/sbrk.c b/src/linux/sbrk.c
new file mode 100644 (file)
index 0000000..56f60d1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stddef.h>
+#include "syscall.h"
+
+void *sbrk(ptrdiff_t inc)
+{
+       return (void *)syscall1(__NR_brk, syscall1(__NR_brk, 0)+inc);
+}
diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c
new file mode 100644 (file)
index 0000000..bfbc40a
--- /dev/null
@@ -0,0 +1,10 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count)
+{
+       return syscall4(__NR_sendfile, out_fd, in_fd, (long)ofs, count);
+}
+
+LFS64(sendfile);
diff --git a/src/linux/setgroups.c b/src/linux/setgroups.c
new file mode 100644 (file)
index 0000000..2368aa0
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int setgroups(int count, const gid_t list[])
+{
+       /* this depends on our gid_t being 32bit */
+       return syscall2(__NR_setgroups32, count, (long)list);
+}
diff --git a/src/linux/sethostname.c b/src/linux/sethostname.c
new file mode 100644 (file)
index 0000000..f61e0cb
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int sethostname(const char *name, size_t len)
+{
+       return syscall2(__NR_sethostname, (long)name, len);
+}
diff --git a/src/linux/settimeofday.c b/src/linux/settimeofday.c
new file mode 100644 (file)
index 0000000..bd7e410
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/time.h>
+#include "syscall.h"
+
+int settimeofday(const struct timeval *tv, void *tz)
+{
+       return syscall2(__NR_settimeofday, (long)tv, 0);
+}
diff --git a/src/linux/signalfd.c b/src/linux/signalfd.c
new file mode 100644 (file)
index 0000000..ecda263
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/signalfd.h>
+#include "syscall.h"
+
+int signalfd(int fd, const sigset_t *sigs, int flags)
+{
+       return syscall3(__NR_signalfd, fd, (long)sigs, 8);
+}
diff --git a/src/linux/stime.c b/src/linux/stime.c
new file mode 100644 (file)
index 0000000..ec3ba82
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/time.h>
+
+int stime(time_t *t)
+{
+       struct timeval tv = { .tv_sec = *t, .tv_usec = 0 };
+       return settimeofday(&tv, (void *)0);
+}
diff --git a/src/linux/swapoff.c b/src/linux/swapoff.c
new file mode 100644 (file)
index 0000000..f6fa794
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/swap.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int swapoff(const char *path)
+{
+       return syscall1(__NR_swapoff, (long)path);
+}
diff --git a/src/linux/swapon.c b/src/linux/swapon.c
new file mode 100644 (file)
index 0000000..13d2876
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/swap.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int swapon(const char *path, int flags)
+{
+       return syscall2(__NR_swapon, (long)path, flags);
+}
diff --git a/src/linux/sysinfo.c b/src/linux/sysinfo.c
new file mode 100644 (file)
index 0000000..9866947
--- /dev/null
@@ -0,0 +1,9 @@
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+struct sysinfo;
+
+int sysinfo(struct sysinfo *info)
+{
+       return syscall1(__NR_sysinfo, (long)info);
+}
diff --git a/src/linux/umount.c b/src/linux/umount.c
new file mode 100644 (file)
index 0000000..c35f994
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/mount.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int umount(const char *special)
+{
+       return syscall1(__NR_umount, (long)special);
+}
diff --git a/src/linux/umount2.c b/src/linux/umount2.c
new file mode 100644 (file)
index 0000000..cab93fd
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/mount.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int umount2(const char *special, int flags)
+{
+       return syscall2(__NR_umount2, (long)special, flags);
+}
diff --git a/src/linux/utimes.c b/src/linux/utimes.c
new file mode 100644 (file)
index 0000000..99a3b2b
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/time.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+int utimes(const char *path, const struct timeval times[2])
+{
+       long ktimes[2];
+       if (times) {
+               ktimes[0] = times[0].tv_sec;
+               ktimes[1] = times[1].tv_sec;
+       }
+       return syscall2(__NR_utime, (long)path, times ? (long)ktimes : 0);
+}
diff --git a/src/linux/wait3.c b/src/linux/wait3.c
new file mode 100644 (file)
index 0000000..dd63707
--- /dev/null
@@ -0,0 +1,11 @@
+#include <sys/wait.h>
+#include <sys/resource.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+pid_t wait4(pid_t, int *, int, struct rusage *);
+
+pid_t wait3(int *status, int options, struct rusage *usage)
+{
+       return wait4(-1, status, options, usage);
+}
diff --git a/src/linux/wait4.c b/src/linux/wait4.c
new file mode 100644 (file)
index 0000000..dda942d
--- /dev/null
@@ -0,0 +1,19 @@
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <string.h>
+#define SYSCALL_STANDALONE
+#include "syscall.h"
+
+pid_t wait4(pid_t pid, int *status, int options, struct rusage *usage)
+{
+       pid_t ret = syscall4(__NR_wait4, pid, (long)status, options, (long)usage);
+       /* Fixup kernel time_t... */
+       if (usage) {
+               long kusage[4];
+               memcpy(kusage, usage, sizeof kusage);
+               memmove((struct timeval *)usage + 2, (long *)usage + 4, sizeof *usage - 2*sizeof(struct timeval));
+               usage->ru_utime = (struct timeval){ kusage[0], kusage[1] };
+               usage->ru_stime = (struct timeval){ kusage[2], kusage[3] };
+       }
+       return ret;
+}
diff --git a/src/locale/catclose.c b/src/locale/catclose.c
new file mode 100644 (file)
index 0000000..02cd3e5
--- /dev/null
@@ -0,0 +1,6 @@
+#include <nl_types.h>
+
+int catclose (nl_catd catd)
+{
+       return 0;
+}
diff --git a/src/locale/catgets.c b/src/locale/catgets.c
new file mode 100644 (file)
index 0000000..bbee898
--- /dev/null
@@ -0,0 +1,6 @@
+#include <nl_types.h>
+
+char *catgets (nl_catd catd, int set_id, int msg_id, const char *s)
+{
+       return (char *)s;
+}
diff --git a/src/locale/catopen.c b/src/locale/catopen.c
new file mode 100644 (file)
index 0000000..4423c4d
--- /dev/null
@@ -0,0 +1,6 @@
+#include <nl_types.h>
+
+nl_catd catopen (const char *name, int oflag)
+{
+       return (nl_catd)-1;
+}
diff --git a/src/locale/duplocale.c b/src/locale/duplocale.c
new file mode 100644 (file)
index 0000000..dd445d4
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <string.h>
+#include "locale_impl.h"
+
+locale_t duplocale(locale_t old)
+{
+       locale_t new;
+       new = calloc(1, sizeof *new);
+       if (new) memcpy(new, old, sizeof *new);
+       return new;
+}
diff --git a/src/locale/freelocale.c b/src/locale/freelocale.c
new file mode 100644 (file)
index 0000000..4e089f2
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+#include "locale_impl.h"
+
+void freelocale(locale_t l)
+{
+       free(l);
+}
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
new file mode 100644 (file)
index 0000000..4e46c7e
--- /dev/null
@@ -0,0 +1,568 @@
+#include <iconv.h>
+#include <errno.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+
+#define UTF_32BE    000
+#define UTF_16LE    001
+#define UTF_16BE    002
+#define UTF_32LE    003
+#define UCS2BE      004
+#define UCS2LE      005
+#define WCHAR_T     007
+
+#define US_ASCII    021
+#define UTF_8       022
+#define LATIN_9     024
+#define TIS_620     025
+#define JIS_0201    026
+
+#define EUC         031
+#define EUC_TW      032
+#define SHIFT_JIS   033
+#define BIG5        034
+#define GBK         035
+
+/* FIXME: these are not implemented yet
+ * EUC:   A1-FE A1-FE
+ * GBK:   81-FE 40-7E,80-FE
+ * Big5:  A1-FE 40-7E,A1-FE
+ */
+
+/* Definitions of charmaps. Each charmap consists of:
+ * 1. Empty-string-terminated list of null-terminated aliases.
+ * 2. Special type code or bits per character.
+ * 3. Number of elided entries (128 for specials).
+ * 4. Character table (size determined by fields 2 and 3). */
+
+static const unsigned char charmaps[] =
+"utf8\0\0\022\x80"
+"wchart\0\0\007\x80"
+
+"ucs2\0ucs2be\0\0\004\x80"
+"ucs2le\0\0\005\x80"
+
+"utf16\0utf16be\0\0\002\x80"
+"utf16le\0\0\001\x80"
+
+"ucs4\0ucs4be\0utf32\0utf32be\0\0\000\x80"
+"ucs4le\0utf32le\0\0\003\x80"
+
+"ascii\0iso646\0usascii\0\0\021\x80"
+"latin1\0iso88591\0\0\x09\x80"
+"latin9\0iso885915\0\0\024\x80"
+"tis620\0iso885911\0\0\025\x80"
+"jis0201\0\0\026\x80"
+
+"iso88592\0\0\x0a\x21"
+"\x04\x61\x1b\x14\x29\x3d\x69\x75\x0a\x2a"
+"\x60\x79\x45\x56\x5e\xad\xf4\xb5\x17\x2c"
+"\x05\x6d\x2b\x14\x2d\x3e\x6d\x75\x2c\x2e"
+"\x61\x7d\x55\x96\x5e\xdd\xfa\xc5\x17\x55"
+"\xc1\x08\x23\x10\x31\x39\x19\x74\x0c\x43"
+"\xc9\x60\xb4\x8c\x46\xcd\x38\xe3\x10\x44"
+"\x43\x1d\x35\x0d\x35\x50\x59\x73\x0d\x56"
+"\x6e\x69\x03\x17\x37\xdd\x88\xf5\x4d\x55"
+"\xe1\x88\x33\x10\x39\x3a\x1d\x74\x4e\x43"
+"\xe9\x64\xb4\xce\x46\xed\xb8\xf3\x50\x44"
+"\x44\x21\x35\x0f\x3d\x51\xd9\x73\x4f\x56"
+"\x6f\xe9\x13\x17\x3f\xfd\x8c\x95\x2d"
+
+"iso88593\0\0\x0a\x21"
+"\x26\x61\x3b\x0a\x29\x00\x90\x74\x0a\x2a"
+"\x30\x79\xe5\x11\x4d\xad\x00\xb0\x17\x2c"
+"\x27\xc9\x32\x0b\x2d\xb5\x94\x74\x0b\x2e"
+"\x31\x7d\xf5\x51\x4d\xbd\x00\xc0\x17\x30"
+"\xc1\x08\x03\x00\x31\x0a\x21\x74\x0c\x32"
+"\xc9\x28\xb3\x0c\x33\xcd\x38\xf3\x0c\x00"
+"\xd1\x48\x33\x0d\x35\x20\x59\x73\x0d\x47"
+"\xd9\x68\xb3\x0d\x37\x6c\x71\xf5\x0d\x38"
+"\xe1\x88\x03\x00\x39\x0b\x25\x74\x0e\x3a"
+"\xe9\xa8\xb3\x0e\x3b\xed\xb8\xf3\x0e\x00"
+"\xf1\xc8\x33\x0f\x3d\x21\xd9\x73\x4f\x47"
+"\xf9\xe8\xb3\x0f\x3f\x6d\x75\x95\x2d"
+
+"iso88594\0\0\x0a\x21"
+"\x04\xe1\x64\x15\x29\x28\xed\x74\x0a\x2a"
+"\x60\x49\x24\x92\x59\xad\xf4\xf5\x0a\x2c"
+"\x05\x6d\x7b\x15\x2d\x29\xf1\x74\x2c\x2e"
+"\x61\x4d\x34\xd2\x59\x4a\xf9\xb5\x14\x40"
+"\xc1\x08\x33\x0c\x31\xc5\x18\xe3\x12\x43"
+"\xc9\x60\xb4\x8c\x45\xcd\x38\xa3\x12\x44"
+"\x45\x31\x65\x13\x35\xd5\x58\x73\x0d\x36"
+"\x72\x69\xb3\x0d\x37\x68\xa9\xf5\x4d\x40"
+"\xe1\x88\x33\x0e\x39\xe5\x98\xf3\x52\x43"
+"\xe9\x64\xb4\xce\x45\xed\xb8\xb3\x52\x44"
+"\x46\x35\x75\x13\x3d\xf5\xd8\x73\x0f\x3e"
+"\x73\xe9\xb3\x0f\x3f\x69\xad\x95\x2d"
+
+"iso88595\0\0\x0e\x21"
+"\x01\x84\x00\x31\x40\x10\x10\x05\x84\x01"
+"\x71\x40\x20\x10\x09\x84\x02\xb1\x40\x30"
+"\x10\xad\x80\x03\xf1\x40\x40\x10\x11\x84"
+"\x04\x31\x41\x50\x10\x15\x84\x05\x71\x41"
+"\x60\x10\x19\x84\x06\xb1\x41\x70\x10\x1d"
+"\x84\x07\xf1\x41\x80\x10\x21\x84\x08\x31"
+"\x42\x90\x10\x25\x84\x09\x71\x42\xa0\x10"
+"\x29\x84\x0a\xb1\x42\xb0\x10\x2d\x84\x0b"
+"\xf1\x42\xc0\x10\x31\x84\x0c\x31\x43\xd0"
+"\x10\x35\x84\x0d\x71\x43\xe0\x10\x39\x84"
+"\x0e\xb1\x43\xf0\x10\x3d\x84\x0f\xf1\x43"
+"\x00\x11\x41\x84\x10\x31\x44\x10\x11\x45"
+"\x84\x11\x71\x44\x20\x11\x49\x84\x12\xb1"
+"\x44\x30\x11\x4d\x84\x13\xf1\x44\x58\x84"
+"\x51\x84\x14\x31\x45\x50\x11\x55\x84\x15"
+"\x71\x45\x60\x11\x59\x84\x16\xb1\x45\x70"
+"\x11\xa7\x80\x17\xf1\x45\x00"
+
+"iso88596\0\0\x0b\x21"
+"\x00\x00\x00\x00\x48\x01\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x18\xdc\x0a\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\xc0\x86\x01\x00\x00"
+"\x00\x7c\x18\x00\x21\x16\xf1\x88\x49\x5c"
+"\x62\x13\x9f\x18\xc5\x29\x56\xf1\x8a\x59"
+"\xdc\x62\x17\xbf\x18\xc6\x31\x96\xf1\x8c"
+"\x69\x5c\x63\x1b\xdf\x18\xc7\x39\xd6\x31"
+"\x00\x00\x00\x00\x00\x00\x00\xc8\x41\x16"
+"\xf2\x90\x89\x5c\x64\x23\x1f\x19\xc9\x49"
+"\x56\xf2\x92\x99\xdc\x64\x27\x3f\x19\xca"
+"\x51\x96\x32\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00"
+
+"iso88597\0\0\x0e\x21"
+"\x18\x60\x06\x38\x0a\xb0\x82\xaf\xa0\x29"
+"\x70\x0a\xa0\x02\xa9\x80\xde\xb0\x0a\xb0"
+"\x02\xad\x00\x00\x50\x01\xc2\x02\xb1\x80"
+"\x2c\x30\x0b\x10\x0e\x85\x83\xe1\x70\x0b"
+"\x20\x0e\x89\x83\xe2\xb0\x0b\x30\x0e\xbd"
+"\x80\xe3\xf0\x38\x40\x0e\x91\x83\xe4\x30"
+"\x39\x50\x0e\x95\x83\xe5\x70\x39\x60\x0e"
+"\x99\x83\xe6\xb0\x39\x70\x0e\x9d\x83\xe7"
+"\xf0\x39\x80\x0e\xa1\x03\x00\x30\x3a\x90"
+"\x0e\xa5\x83\xe9\x70\x3a\xa0\x0e\xa9\x83"
+"\xea\xb0\x3a\xb0\x0e\xad\x83\xeb\xf0\x3a"
+"\xc0\x0e\xb1\x83\xec\x30\x3b\xd0\x0e\xb5"
+"\x83\xed\x70\x3b\xe0\x0e\xb9\x83\xee\xb0"
+"\x3b\xf0\x0e\xbd\x83\xef\xf0\x3b\x00\x0f"
+"\xc1\x83\xf0\x30\x3c\x10\x0f\xc5\x83\xf1"
+"\x70\x3c\x20\x0f\xc9\x83\xf2\xb0\x3c\x30"
+"\x0f\xcd\x83\xf3\x00\x00\x00"
+
+"iso88598\0\0\x0e\x21"
+"\x00\x80\x28\x30\x0a\x90\x02\xa5\x80\x29"
+"\x70\x0a\xa0\x02\xa9\xc0\x35\xb0\x0a\xb0"
+"\x02\xad\x80\x2b\xf0\x0a\xc0\x02\xb1\x80"
+"\x2c\x30\x0b\xd0\x02\xb5\x80\x2d\x70\x0b"
+"\xe0\x02\xb9\xc0\x3d\xb0\x0b\xf0\x02\xbd"
+"\x80\x2f\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x70\x01"
+"\x42\x17\xd1\x85\x74\x31\x5d\x50\x17\xd5"
+"\x85\x75\x71\x5d\x60\x17\xd9\x85\x76\xb1"
+"\x5d\x70\x17\xdd\x85\x77\xf1\x5d\x80\x17"
+"\xe1\x85\x78\x31\x5e\x90\x17\xe5\x85\x79"
+"\x71\x5e\xa0\x17\xe9\x85\x7a\x01\x00\x00"
+"\x00\x0e\xe0\x03\x08\x00\x00"
+
+"iso88599\0\0\x09\x50"
+"\x1e\xa3\x49\x9b\x46\xad\x9a\xb5\x6b\xd8"
+"\xb2\x69\xdb\xc6\x0d\xa6\xd7\x6f\xe0\xc2"
+"\x89\x1b\x47\xae\x9c\xb9\x73\xe8\xd2\xa9"
+"\x5b\xc7\xae\x9d\xbb\x77\x1f\xe3\xc9\x9b"
+"\x47\xaf\x9e\xbd\x7b\xf8\xf2\xe9\xdb\xc7"
+"\x2f\xe6\xd7\x7f"
+
+"iso885910\0\0\x0e\x21"
+"\x04\x81\x44\x20\x12\xa8\x04\x28\x81\x4d"
+"\x70\x0a\xec\x04\x10\x01\x58\x60\x16\xf4"
+"\x05\xad\x80\x5a\xa0\x14\xc0\x02\x05\xc1"
+"\x44\x30\x12\xac\x04\x29\xc1\x4d\x70\x0b"
+"\xf0\x04\x11\x41\x58\x70\x16\xf8\x05\x15"
+"\xe0\x5a\xb0\x14\x00\x04\xc1\x80\x30\x30"
+"\x0c\x10\x03\xc5\x80\x31\xe0\x12\x30\x04"
+"\xc9\x00\x46\xb0\x0c\x58\x04\xcd\x80\x33"
+"\xf0\x0c\x40\x03\x45\x01\x53\x30\x0d\x50"
+"\x03\xd5\x80\x35\x80\x16\x60\x03\x72\x81"
+"\x36\xb0\x0d\x70\x03\xdd\x80\x37\xf0\x0d"
+"\x04\x04\xe1\x80\x38\x30\x0e\x90\x03\xe5"
+"\x80\x39\xf0\x12\x34\x04\xe9\x40\x46\xb0"
+"\x0e\x5c\x04\xed\x80\x3b\xf0\x0e\xc0\x03"
+"\x46\x41\x53\x30\x0f\xd0\x03\xf5\x80\x3d"
+"\x90\x16\xe0\x03\x73\x81\x3e\xb0\x0f\xf0"
+"\x03\xfd\x80\x3f\x80\x13\x00"
+
+"iso885913\0\0\x0e\x21"
+"\x1d\xa0\x28\x30\x0a\x90\x02\x1e\xa0\x29"
+"\x70\x0a\x60\x03\xa9\x80\x55\xb0\x0a\xb0"
+"\x02\xad\x80\x2b\x60\x0c\xc0\x02\xb1\x80"
+"\x2c\x30\x0b\x70\x80\xb5\x80\x2d\x70\x0b"
+"\xe0\x03\xb9\xc0\x55\xb0\x0b\xf0\x02\xbd"
+"\x80\x2f\x60\x0e\x10\x04\x2e\x01\x40\x60"
+"\x10\x10\x03\xc5\x00\x46\x20\x11\x30\x04"
+"\xc9\x40\x5e\x60\x11\x88\x04\x36\x81\x4a"
+"\xb0\x13\x80\x05\x43\x41\x51\x30\x0d\x30"
+"\x05\xd5\x80\x35\x70\x0d\xc8\x05\x41\x81"
+"\x56\xa0\x16\x70\x03\x7b\x41\x5f\xf0\x0d"
+"\x14\x04\x2f\x41\x40\x70\x10\x90\x03\xe5"
+"\x40\x46\x30\x11\x34\x04\xe9\x80\x5e\x70"
+"\x11\x8c\x04\x37\xc1\x4a\xc0\x13\x84\x05"
+"\x44\x81\x51\x30\x0f\x34\x05\xf5\x80\x3d"
+"\x70\x0f\xcc\x05\x42\xc1\x56\xb0\x16\xf0"
+"\x03\x7c\x81\x5f\x90\x01\x02"
+
+"iso885914\0\0\x0d\x21"
+"\x02\x7e\xc0\x8f\x02\x85\xb0\x10\x14\xfc"
+"\x29\x00\xf4\xa9\x40\xd0\x2f\x78\x79\xdf"
+"\x0a\x5c\x01\x5e\xf0\xf0\x1f\x1e\x24\x84"
+"\x04\x20\x1f\xe4\x6d\x81\x95\x0f\xf4\x57"
+"\x7e\xd0\x83\xf9\x79\x4f\xe8\x0b\x7d\x98"
+"\x07\x06\xc1\x40\x18\x0c\x03\x62\x50\x0c"
+"\x8c\xc1\x31\x40\x06\xc9\x40\x19\x2c\x03"
+"\x66\xd0\x0c\x9c\xc1\x33\xa0\x0b\xd1\x40"
+"\x1a\x4c\x03\x6a\x50\x0d\xac\x81\x9a\xc7"
+"\x06\xd9\x40\x1b\x6c\x03\x6e\xd0\x0d\xec"
+"\xc2\x37\x00\x07\xe1\x40\x1c\x8c\x03\x72"
+"\x50\x0e\xcc\xc1\x39\x40\x07\xe9\x40\x1d"
+"\xac\x03\x76\xd0\x0e\xdc\xc1\x3b\xa8\x0b"
+"\xf1\x40\x1e\xcc\x03\x7a\x50\x0f\xec\xc1"
+"\x9a\xc7\x07\xf9\x40\x1f\xec\x03\x7e\xd0"
+"\x0f\xee\xc2\x3f\x00"
+
+"iso885916\0\0\x0e\x21"
+"\x04\x41\x41\x10\x14\xb0\x82\x1e\x20\x58"
+"\x70\x0a\x84\x05\xa9\x00\x86\xb0\x0a\xe4"
+"\x05\xad\x80\x5e\xb0\x17\xc0\x02\xb1\x00"
+"\x43\x20\x14\xf4\x05\x1d\xa0\x2d\x70\x0b"
+"\xf8\x05\x0d\x41\x86\xb0\x0b\x48\x05\x53"
+"\x01\x5e\xc0\x17\x00\x03\xc1\x80\x30\x20"
+"\x10\x10\x03\x06\x81\x31\x70\x0c\x20\x03"
+"\xc9\x80\x32\xb0\x0c\x30\x03\xcd\x80\x33"
+"\xf0\x0c\x40\x04\x43\x81\x34\x30\x0d\x50"
+"\x03\x50\x81\x35\xa0\x15\xc0\x05\xd9\x80"
+"\x36\xb0\x0d\x70\x03\x18\x81\x86\xf0\x0d"
+"\x80\x03\xe1\x80\x38\x30\x10\x90\x03\x07"
+"\x81\x39\x70\x0e\xa0\x03\xe9\x80\x3a\xb0"
+"\x0e\xb0\x03\xed\x80\x3b\xf0\x0e\x44\x04"
+"\x44\x81\x3c\x30\x0f\xd0\x03\x51\x81\x3d"
+"\xb0\x15\xc4\x05\xf9\x80\x3e\xb0\x0f\xf0"
+"\x03\x19\xc1\x86\xf0\x0f\x00"
+
+"windows1252\0\0\x0e\x00"
+"\xac\x20\x00\xa0\x01\x4a\x06\x1e\xa0\x09"
+"\x08\x02\x86\x80\xc6\x02\x0c\x08\x16\xe4"
+"\x80\x52\x01\x00\xd0\x17\x00\x00\x00\x00"
+"\x06\x98\x01\x72\x80\x1d\xa0\x08\x38\x01"
+"\x52\x80\xdc\x82\x48\x18\x16\xe8\x80\x53"
+"\x01\x00\xe0\x17\xe0\x05\xa0\x40\x28\x20"
+"\x0a\x8c\x02\xa4\x40\x29\x60\x0a\x9c\x02"
+"\xa8\x40\x2a\xa0\x0a\xac\x02\xac\x40\x2b"
+"\xe0\x0a\xbc\x02\xb0\x40\x2c\x20\x0b\xcc"
+"\x02\xb4\x40\x2d\x60\x0b\xdc\x02\xb8\x40"
+"\x2e\xa0\x0b\xec\x02\xbc\x40\x2f\xe0\x0b"
+"\xfc\x02\xc0\x40\x30\x20\x0c\x0c\x03\xc4"
+"\x40\x31\x60\x0c\x1c\x03\xc8\x40\x32\xa0"
+"\x0c\x2c\x03\xcc\x40\x33\xe0\x0c\x3c\x03"
+"\xd0\x40\x34\x20\x0d\x4c\x03\xd4\x40\x35"
+"\x60\x0d\x5c\x03\xd8\x40\x36\xa0\x0d\x6c"
+"\x03\xdc\x40\x37\xe0\x0d\x7c\x03\xe0\x40"
+"\x38\x20\x0e\x8c\x03\xe4\x40\x39\x60\x0e"
+"\x9c\x03\xe8\x40\x3a\xa0\x0e\xac\x03\xec"
+"\x40\x3b\xe0\x0e\xbc\x03\xf0\x40\x3c\x20"
+"\x0f\xcc\x03\xf4\x40\x3d\x60\x0f\xdc\x03"
+"\xf8\x40\x3e\xa0\x0f\xec\x03\xfc\x40\x3f"
+"\xe0\x0f\xfc\x03"
+;
+
+
+
+static int fuzzycmp(const char *a, const char *b)
+{
+       for (; *a && *b; a++, b++) {
+               while (*a && (*a|32U)-'a'>26 && *a-'0'>10U) a++;
+               if ((*a|32U) != *b) return 1;
+       }
+       return *a != *b;
+}
+
+static int find_charmap(const char *name)
+{
+       const unsigned char *s;
+       for (s=charmaps; *s; ) {
+               if (!fuzzycmp(name, s)) {
+                       for (; *s; s+=strlen(s)+1);
+                       return s+1-charmaps;
+               }
+               s += strlen(s)+1;
+               if (!*s) s += ((128-s[2])*s[1]+7)/8 + 3;
+       }
+       return -1;
+}
+
+iconv_t iconv_open(const char *to, const char *from)
+{
+       int f, t;
+
+       if ((t = find_charmap(to)) < 0 || (f = find_charmap(from)) < 0) {
+               errno = EINVAL;
+               return (iconv_t)-1;
+       }
+
+       return (void *)(f<<16 | t);
+}
+
+int iconv_close(iconv_t cd)
+{
+       return 0;
+}
+
+static unsigned get_16(const unsigned char *s, int e)
+{
+       e &= 1;
+       return s[e]<<8 | s[1-e];
+}
+
+static void put_16(unsigned char *s, unsigned c, int e)
+{
+       e &= 1;
+       s[e] = c>>8;
+       s[1-e] = c;
+}
+
+static unsigned get_32(const unsigned char *s, int e)
+{
+       return s[e]+0U<<24 | s[e^1]<<16 | s[e^2]<<8 | s[e^3];
+}
+
+static void put_32(unsigned char *s, unsigned c, int e)
+{
+       s[e^0] = c>>24;
+       s[e^1] = c>>16;
+       s[e^2] = c>>8;
+       s[e^3] = c;
+}
+
+
+
+#define GET_MAPPING(m, i, n) ( (1<<(n))-1 & ( \
+       (m)[(i)*(n)/8] >> ((n)%8*(i)%8) | \
+       (m)[(i)*(n)/8+1] << 8-((n)%8*(i)%8) | \
+       (m)[(i)*(n)/8+2] << 16-((n)%8*(i)%8)     ) )
+
+static unsigned get_mapping(const unsigned char *m, unsigned c, unsigned n)
+{
+       switch (n) {
+       default:
+       case 9:  return m[c*9/8]>>c%8 | m[c*9/8+1]<<8-c%8 & (1<<n)-1;
+       case 10: return m[c*10/8]>>2*c%8 | m[c*10/8+1]<<8-2*c%8 & (1<<n)-1;
+       case 11: return GET_MAPPING(m, c, 11);
+       case 13: return GET_MAPPING(m, c, 13);
+       case 14: return GET_MAPPING(m, c, 14);
+       }
+}
+
+/* Adapt as needed */
+#define mbrtowc_utf8 mbrtowc
+#define wctomb_utf8 wctomb
+
+#include <stdio.h>
+size_t iconv(iconv_t cd0, char **in, size_t *inb, char **out, size_t *outb)
+{
+       size_t x=0;
+       unsigned long cd = (unsigned long)cd0;
+       unsigned to = cd & 0xffff;
+       unsigned from = cd >> 16;
+       const unsigned char *map = charmaps+from+2;
+       const unsigned char *tomap = charmaps+to+2;
+       mbstate_t st = {0};
+       wchar_t wc;
+       unsigned c, d;
+       size_t k, l;
+       int err;
+       unsigned elide = map[-1] + 128;
+       unsigned toelide = tomap[-1] + 128;
+       unsigned char type = map[-2];
+       unsigned char totype = tomap[-2];
+
+       if (!in || !*in || !*inb) return 0;
+
+       for (; *inb; *in+=l, *inb-=l) {
+               c = *(unsigned char *)*in;
+               l = 1;
+               if (type < 8 || c >= 0x80) switch (type) {
+               case UTF_8:
+                       l = mbrtowc_utf8(&wc, *in, *inb, &st);
+                       if (!l) l++;
+                       else if (l == (size_t)-1) goto ilseq;
+                       else if (l == (size_t)-2) goto starved;
+                       c = wc;
+                       break;
+               case LATIN_9:
+                       if ((unsigned)c - 0xa4 <= 0xbe - 0xa4) {
+                               static const unsigned char map[] = {
+                                       0, 0x60, 0, 0x61, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0x7d, 0, 0, 0, 0x7e, 0, 0, 0,
+                                       0x52, 0x53, 0x78
+                               };
+                               if (c == 0xa4) c = 0x20ac;
+                               else if (map[c-0xa5]) c = 0x100 | map[c-0xa5];
+                       }
+                       break;
+               case TIS_620:
+                       if (c >= 0xa1) c += 0x0e01-0xa1;
+                       break;
+               case JIS_0201:
+                       if (c >= 0xa1)
+                               if (c <= 0xdf) c += 0xff61-0xa1;
+                               else goto ilseq;
+                       break;
+               case 9: case 10: case 11: case 13: case 14:
+                       if (c < elide) break;
+                       c = get_mapping(map, c-elide, type);
+                       if (!c) {
+               case US_ASCII:
+                               goto ilseq;
+                       }
+                       break;
+               case WCHAR_T:
+                       l = sizeof(wchar_t);
+                       if (*inb < l) goto starved;
+                       c = *(wchar_t *)*in;
+                       if (0) {
+               case UTF_32BE:
+               case UTF_32LE:
+                       l = 4;
+                       if (*inb < 4) goto starved;
+                       c = get_32(*in, type);
+                       }
+                       if (c-0xd800u < 0x800u || c >= 0x110000u) goto ilseq;
+                       break;
+               case UCS2BE:
+               case UCS2LE:
+               case UTF_16BE:
+               case UTF_16LE:
+                       l = 2;
+                       if (*inb < 2) goto starved;
+                       c = get_16(*in, type);
+                       if ((unsigned)(c-0xdc00) < 0x400) goto ilseq;
+                       if ((unsigned)(c-0xd800) < 0x400) {
+                               if (type-UCS2BE < 2U) goto ilseq;
+                               l = 4;
+                               if (*inb < 4) goto starved;
+                               d = get_16(*in + 2, from);
+                               if ((unsigned)(c-0xdc00) >= 0x400) goto ilseq;
+                               c = ((c-0xd800)<<10) | (d-0xdc00);
+                       }
+                       break;
+               }
+
+               switch (totype) {
+               case WCHAR_T:
+                       if (*outb < sizeof(wchar_t)) goto toobig;
+                       *(wchar_t *)*out = c;
+                       *out += sizeof(wchar_t);
+                       *outb -= sizeof(wchar_t);
+                       break;
+               case UTF_8:
+                       if (*outb < 4) {
+                               char tmp[4];
+                               k = wctomb_utf8(tmp, c);
+                               if (*outb < k) goto toobig;
+                               memcpy(*out, tmp, k);
+                       } else k = wctomb_utf8(*out, c);
+                       *out += k;
+                       *outb -= k;
+                       break;
+               case TIS_620:
+                       if (c-0xe01u <= 0xff-0xa1)
+                               c -= 0xe01-0xa1;
+                       else if (c >= 0xa1)
+                               goto ascii;
+                       goto revout;
+               case JIS_0201:
+                       if (c-0xff61u <= 0xdf-0xa1)
+                               c -= 0xff61-0xa1;
+                       else if (c >= 0xa1)
+                               goto ascii;
+                       goto revout;
+               case LATIN_9:
+                       if (c == 0x20ac) {
+                               c=0xa4;
+                       } else if (c-0x150u<=0x12 && (1<<c-0x150 & 0x3000c)) {
+                               static const unsigned char map[] =
+                                       { 0xa6,0xa8,0xbc,0xbd };
+                               c = map[c&3];
+                       } else if (c-0x178u<=0x7 && (1<<c-0x178 & 0x61)) {
+                               static const unsigned char map[] =
+                                       { 0xbe,0,0,0,0,0xb4,0xb8 };
+                               c = map[c&7];
+                       } else if (c>0x100 ||
+                               c-0xa5u<=0xbeu-0xa5
+                               && (1<<c-0xa5 & 0x388800a))
+               case US_ASCII: ascii:
+                       if (c > 0x7f) x++, c='*';
+               case 9: case 10: case 11: case 13: case 14:
+                       if (*outb < 1) goto toobig;
+                       if (c < toelide) {
+                       revout:
+                               *(*out)++ = c;
+                               *outb -= 1;
+                               break;
+                       }
+                       for (d=0; d<256-toelide; d++) {
+                               if (c == get_mapping(tomap, d, totype)) {
+                                       c = d + toelide;
+                                       goto revout;
+                               }
+                       }
+                       x++;
+                       c = '*';
+                       goto revout;
+               case UCS2BE:
+               case UCS2LE:
+               case UTF_16BE:
+               case UTF_16LE:
+                       if (c < 0x10000) {
+                               if (*outb < 2) goto toobig;
+                               put_16(*out, c, totype);
+                               *out += 2;
+                               *outb -= 2;
+                               break;
+                       }
+                       if (type-UCS2BE < 2U) goto ilseq;
+                       if (*outb < 4) goto toobig;
+                       put_16(*out, (c>>10)|0xd800, totype);
+                       put_16(*out + 2, (c&0x3ff)|0xdc00, totype);
+                       *out += 4;
+                       *outb -= 4;
+                       break;
+               case UTF_32BE:
+               case UTF_32LE:
+                       if (*outb < 4) goto toobig;
+                       put_32(*out, c, totype);
+                       *out += 4;
+                       *outb -= 4;
+                       break;
+               }
+       }
+       return x;
+ilseq:
+       err = EILSEQ;
+       x = -1;
+       goto end;
+toobig:
+       err = E2BIG;
+       goto end;
+starved:
+       err = EINVAL;
+end:
+       errno = err;
+       return x;
+}
diff --git a/src/locale/intl.c b/src/locale/intl.c
new file mode 100644 (file)
index 0000000..964f7da
--- /dev/null
@@ -0,0 +1,67 @@
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+
+char *gettext(const char *msgid)
+{
+       return (char *) msgid;
+}
+
+char *dgettext(const char *domainname, const char *msgid)
+{
+       return (char *) msgid;
+}
+
+char *dcgettext(const char *domainname, const char *msgid, int category)
+{
+       return (char *) msgid;
+}
+
+char *ngettext(const char *msgid1, const char *msgid2, unsigned long int n)
+{
+       return (char *) ((n == 1) ? msgid1 : msgid2);
+}
+
+char *dngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long int n)
+{
+       return (char *) ((n == 1) ? msgid1 : msgid2);
+}
+
+char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long int n, int category)
+{
+       return (char *) ((n == 1) ? msgid1 : msgid2);
+}
+
+char *textdomain(const char *domainname)
+{
+       static const char default_str[] = "messages";
+
+       if (domainname && *domainname && strcmp(domainname, default_str)) {
+               errno = EINVAL;
+               return NULL;
+       }
+       return (char *) default_str;
+}
+
+char *bindtextdomain(const char *domainname, const char *dirname)
+{
+       static const char dir[] = "/";
+
+       if (!domainname || !*domainname
+               || (dirname && ((dirname[0] != '/') || dirname[1]))
+               ) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       return (char *) dir;
+}
+
+char *bind_textdomain_codeset(const char *domainname, const char *codeset)
+{
+       if (!domainname || !*domainname || (codeset && strcasecmp(codeset, "UTF-8"))) {
+               errno = EINVAL;
+       }
+       return NULL;
+}
diff --git a/src/locale/isalnum_l.c b/src/locale/isalnum_l.c
new file mode 100644 (file)
index 0000000..b8a6eef
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isalnum_l(int c, locale_t l)
+{
+       return isalnum(c);
+}
diff --git a/src/locale/isalpha_l.c b/src/locale/isalpha_l.c
new file mode 100644 (file)
index 0000000..2e1205c
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isalpha_l(int c, locale_t l)
+{
+       return isalpha(c);
+}
diff --git a/src/locale/isblank_l.c b/src/locale/isblank_l.c
new file mode 100644 (file)
index 0000000..27479aa
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isblank_l(int c, locale_t l)
+{
+       return isblank(c);
+}
diff --git a/src/locale/iscntrl_l.c b/src/locale/iscntrl_l.c
new file mode 100644 (file)
index 0000000..ca596fa
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int iscntrl_l(int c, locale_t l)
+{
+       return iscntrl(c);
+}
diff --git a/src/locale/isdigit_l.c b/src/locale/isdigit_l.c
new file mode 100644 (file)
index 0000000..c8ae7bd
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isdigit_l(int c, locale_t l)
+{
+       return isdigit(c);
+}
diff --git a/src/locale/isgraph_l.c b/src/locale/isgraph_l.c
new file mode 100644 (file)
index 0000000..713a86e
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isgraph_l(int c, locale_t l)
+{
+       return isgraph(c);
+}
diff --git a/src/locale/islower_l.c b/src/locale/islower_l.c
new file mode 100644 (file)
index 0000000..25ec97a
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int islower_l(int c, locale_t l)
+{
+       return islower(c);
+}
diff --git a/src/locale/isprint_l.c b/src/locale/isprint_l.c
new file mode 100644 (file)
index 0000000..79ef351
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isprint_l(int c, locale_t l)
+{
+       return isprint(c);
+}
diff --git a/src/locale/ispunct_l.c b/src/locale/ispunct_l.c
new file mode 100644 (file)
index 0000000..1c0bd04
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int ispunct_l(int c, locale_t l)
+{
+       return ispunct(c);
+}
diff --git a/src/locale/isspace_l.c b/src/locale/isspace_l.c
new file mode 100644 (file)
index 0000000..e1a0efe
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isspace_l(int c, locale_t l)
+{
+       return isspace(c);
+}
diff --git a/src/locale/isupper_l.c b/src/locale/isupper_l.c
new file mode 100644 (file)
index 0000000..11ba703
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isupper_l(int c, locale_t l)
+{
+       return isupper(c);
+}
diff --git a/src/locale/isxdigit_l.c b/src/locale/isxdigit_l.c
new file mode 100644 (file)
index 0000000..68649d0
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isxdigit_l(int c, locale_t l)
+{
+       return isxdigit(c);
+}
diff --git a/src/locale/langinfo.c b/src/locale/langinfo.c
new file mode 100644 (file)
index 0000000..f7f5601
--- /dev/null
@@ -0,0 +1,58 @@
+#include <locale.h>
+#include <langinfo.h>
+
+static const char c_time[] =
+       "Sun\0" "Mon\0" "Tue\0" "Wed\0" "Thu\0" "Fri\0" "Sat\0"
+       "Sunday\0" "Monday\0" "Tuesday\0" "Wednesday\0"
+       "Thursday\0" "Friday\0" "Saturday\0"
+       "Jan\0" "Feb\0" "Mar\0" "Apr\0" "May\0" "Jun\0"
+       "Jul\0" "Aug\0" "Sep\0" "Oct\0" "Nov\0" "Dec\0"
+       "January\0"   "February\0" "March\0"    "April\0"
+       "May\0"       "June\0"     "July\0"     "August\0"
+       "September\0" "October\0"  "November\0" "December\0"
+       "AM\0" "PM\0"
+       "%a %b %e %T %Y\0"
+       "%m/%d/%y\0"
+       "%H:%M:%S\0"
+       "%I:%M:%S %p\0"
+       "\0"
+       "%m/%d/%y\0"
+       "0123456789"
+       "%a %b %e %T %Y\0"
+       "%H:%M:%S";
+
+static const char c_messages[] = "^[yY]\0" "^[nN]";
+static const char c_numeric[] = ".\0" "";
+
+const char *__langinfo(nl_item item)
+{
+       int cat = item >> 16;
+       int idx = item & 65535;
+       const char *str;
+
+       if (item == CODESET) return "UTF-8";
+       
+       switch (cat) {
+       case LC_NUMERIC:
+               if (idx > 1) return NULL;
+               str = c_numeric;
+               break;
+       case LC_TIME:
+               if (idx > 0x31) return NULL;
+               str = c_time;
+               break;
+       case LC_MONETARY:
+               if (idx > 0) return NULL;
+               str = "";
+               break;
+       case LC_MESSAGES:
+               if (idx > 1) return NULL;
+               str = c_messages;
+               break;
+       default:
+               return NULL;
+       }
+
+       for (; idx; idx--, str++) for (; *str; str++);
+       return str;
+}
diff --git a/src/locale/localeconv.c b/src/locale/localeconv.c
new file mode 100644 (file)
index 0000000..d79d1c0
--- /dev/null
@@ -0,0 +1,22 @@
+#include <locale.h>
+#include <string.h>
+#include <stdlib.h>
+
+struct lconv *localeconv(void)
+{
+       static struct lconv *posix_lconv;
+       if (posix_lconv) return posix_lconv;
+       posix_lconv = malloc(sizeof *posix_lconv);
+       memset(posix_lconv, -1, sizeof *posix_lconv);
+       posix_lconv->decimal_point = ".";
+       posix_lconv->thousands_sep = "";
+       posix_lconv->grouping = "\xff";
+       posix_lconv->int_curr_symbol = ""; //"\xc2\xa4";
+       posix_lconv->currency_symbol = "";
+       posix_lconv->mon_decimal_point = "";
+       posix_lconv->mon_thousands_sep = "";
+       posix_lconv->mon_grouping = "\xff";
+       posix_lconv->positive_sign = ""; // "+";
+       posix_lconv->negative_sign = ""; // "-";
+       return posix_lconv;
+}
diff --git a/src/locale/newlocale.c b/src/locale/newlocale.c
new file mode 100644 (file)
index 0000000..986e796
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <string.h>
+#include "locale_impl.h"
+
+locale_t newlocale(int mask, const char *name, locale_t base)
+{
+       if (*name && strcmp(name, "C") && strcmp(name, "POSIX"))
+               return 0;
+       if (!base) base = calloc(1, sizeof *base);
+       return base;
+}
diff --git a/src/locale/nl_langinfo.c b/src/locale/nl_langinfo.c
new file mode 100644 (file)
index 0000000..bb3a2c4
--- /dev/null
@@ -0,0 +1,13 @@
+#include <langinfo.h>
+
+// FIXME: other items
+
+char *nl_langinfo(nl_item item)
+{
+       switch (item) {
+       case CODESET:
+               return "UTF-8";
+       default:
+               return "";
+       }
+}
diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c
new file mode 100644 (file)
index 0000000..28f29b8
--- /dev/null
@@ -0,0 +1,9 @@
+#include <locale.h>
+
+char *setlocale(int category, const char *locale)
+{
+       /* Note: plain "C" would be better, but puts some broken
+        * software into legacy 8-bit-codepage mode, ignoring
+        * the standard library's multibyte encoding */
+       return "C.UTF-8";
+}
diff --git a/src/locale/strcoll.c b/src/locale/strcoll.c
new file mode 100644 (file)
index 0000000..30bccd6
--- /dev/null
@@ -0,0 +1,6 @@
+#include <string.h>
+
+int strcoll(const char *l, const char *r)
+{
+       return strcmp(l, r);
+}
diff --git a/src/locale/strxfrm.c b/src/locale/strxfrm.c
new file mode 100644 (file)
index 0000000..8f12339
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+
+/* collate only by code points */
+size_t strxfrm(char *dest, const char *src, size_t n)
+{
+       size_t l = strlen(src);
+       if (n > l) strcpy(dest, src);
+       return l;
+}
diff --git a/src/locale/tmp b/src/locale/tmp
new file mode 100644 (file)
index 0000000..aa71779
--- /dev/null
@@ -0,0 +1,390 @@
+"iso88591\0\x08\x80"
+"iso88592\0\x0a\x21"
+"\x04\x61\x1b\x14\x29\x3d\x69\x75\x0a\x2a"
+"\x60\x79\x45\x56\x5e\xad\xf4\xb5\x17\x2c"
+"\x05\x6d\x2b\x14\x2d\x3e\x6d\x75\x2c\x2e"
+"\x61\x7d\x55\x96\x5e\xdd\xfa\xc5\x17\x55"
+"\xc1\x08\x23\x10\x31\x39\x19\x74\x0c\x43"
+"\xc9\x60\xb4\x8c\x46\xcd\x38\xe3\x10\x44"
+"\x43\x1d\x35\x0d\x35\x50\x59\x73\x0d\x56"
+"\x6e\x69\x03\x17\x37\xdd\x88\xf5\x4d\x55"
+"\xe1\x88\x33\x10\x39\x3a\x1d\x74\x4e\x43"
+"\xe9\x64\xb4\xce\x46\xed\xb8\xf3\x50\x44"
+"\x44\x21\x35\x0f\x3d\x51\xd9\x73\x4f\x56"
+"\x6f\xe9\x13\x17\x3f\xfd\x8c\x95\x2d"
+"iso88593\0\x0a0x21"
+"\x26\x61\x3b\x0a\x29\x00\x90\x74\x0a\x2a"
+"\x30\x79\xe5\x11\x4d\xad\x00\xb0\x17\x2c"
+"\x27\xc9\x32\x0b\x2d\xb5\x94\x74\x0b\x2e"
+"\x31\x7d\xf5\x51\x4d\xbd\x00\xc0\x17\x30"
+"\xc1\x08\x03\x00\x31\x0a\x21\x74\x0c\x32"
+"\xc9\x28\xb3\x0c\x33\xcd\x38\xf3\x0c\x00"
+"\xd1\x48\x33\x0d\x35\x20\x59\x73\x0d\x47"
+"\xd9\x68\xb3\x0d\x37\x6c\x71\xf5\x0d\x38"
+"\xe1\x88\x03\x00\x39\x0b\x25\x74\x0e\x3a"
+"\xe9\xa8\xb3\x0e\x3b\xed\xb8\xf3\x0e\x00"
+"\xf1\xc8\x33\x0f\x3d\x21\xd9\x73\x4f\x47"
+"\xf9\xe8\xb3\x0f\x3f\x6d\x75\x95\x2d"
+"iso88594\0\x0a\x21"
+"\x04\xe1\x64\x15\x29\x28\xed\x74\x0a\x2a"
+"\x60\x49\x24\x92\x59\xad\xf4\xf5\x0a\x2c"
+"\x05\x6d\x7b\x15\x2d\x29\xf1\x74\x2c\x2e"
+"\x61\x4d\x34\xd2\x59\x4a\xf9\xb5\x14\x40"
+"\xc1\x08\x33\x0c\x31\xc5\x18\xe3\x12\x43"
+"\xc9\x60\xb4\x8c\x45\xcd\x38\xa3\x12\x44"
+"\x45\x31\x65\x13\x35\xd5\x58\x73\x0d\x36"
+"\x72\x69\xb3\x0d\x37\x68\xa9\xf5\x4d\x40"
+"\xe1\x88\x33\x0e\x39\xe5\x98\xf3\x52\x43"
+"\xe9\x64\xb4\xce\x45\xed\xb8\xb3\x52\x44"
+"\x46\x35\x75\x13\x3d\xf5\xd8\x73\x0f\x3e"
+"\x73\xe9\xb3\x0f\x3f\x69\xad\x95\x2d"
+"iso88595\0\x0d\x21"
+"\x01\x84\x00\x30\x40\x10\x10\x05\x84\x01"
+"\x70\x40\x20\x10\x09\x84\x02\xb0\x40\x30"
+"\x10\xad\x80\x03\xf0\x40\x40\x10\x11\x84"
+"\x04\x30\x41\x50\x10\x15\x84\x05\x70\x41"
+"\x60\x10\x19\x84\x06\xb0\x41\x70\x10\x1d"
+"\x84\x07\xf0\x41\x80\x10\x21\x84\x08\x30"
+"\x42\x90\x10\x25\x84\x09\x70\x42\xa0\x10"
+"\x29\x84\x0a\xb0\x42\xb0\x10\x2d\x84\x0b"
+"\xf0\x42\xc0\x10\x31\x84\x0c\x30\x43\xd0"
+"\x10\x35\x84\x0d\x70\x43\xe0\x10\x39\x84"
+"\x0e\xb0\x43\xf0\x10\x3d\x84\x0f\xf0\x43"
+"\x00\x11\x41\x84\x10\x30\x44\x10\x11\x45"
+"\x84\x11\x70\x44\x20\x11\x49\x84\x12\xb0"
+"\x44\x30\x11\x4d\x84\x13\xf0\x44\x58\x84"
+"\x51\x84\x14\x30\x45\x50\x11\x55\x84\x15"
+"\x70\x45\x60\x11\x59\x84\x16\xb0\x45\x70"
+"\x11\xa7\x80\x17\xf0\x45\x00"
+"iso88596\0\x0b\x21"
+"\x00\x00\x00\x00\x48\x01\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x18\xdc\x0a\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\xc0\x86\x00\x00\x00"
+"\x00\x7c\x18\x00\x21\x16\xf1\x88\x48\x5c"
+"\x62\x13\x9c\x18\xc5\x29\x56\xf1\x8a\x58"
+"\xdc\x62\x17\xbc\x18\xc6\x31\x96\xf1\x8c"
+"\x68\x5c\x63\x1b\xdc\x18\xc7\x39\xd6\x31"
+"\x00\x00\x00\x00\x00\x00\x00\xc8\x41\x16"
+"\xf2\x90\x88\x5c\x64\x23\x1c\x19\xc9\x49"
+"\x56\xf2\x92\x98\xdc\x64\x27\x3c\x19\xca"
+"\x51\x96\x32\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00"
+"iso88597\0\x0d\x21"
+"\x18\x60\x06\x30\x0a\xb0\x82\xaf\xa0\x29"
+"\x70\x0a\xa0\x02\xa9\x80\xde\xb0\x0a\xb0"
+"\x02\xad\x00\x00\x50\x01\xc0\x02\xb1\x80"
+"\x2c\x30\x0b\x10\x0e\x85\x83\xe1\x70\x0b"
+"\x20\x0e\x89\x83\xe2\xb0\x0b\x30\x0e\xbd"
+"\x80\xe3\xf0\x38\x40\x0e\x91\x83\xe4\x30"
+"\x39\x50\x0e\x95\x83\xe5\x70\x39\x60\x0e"
+"\x99\x83\xe6\xb0\x39\x70\x0e\x9d\x83\xe7"
+"\xf0\x39\x80\x0e\xa1\x03\x00\x30\x3a\x90"
+"\x0e\xa5\x83\xe9\x70\x3a\xa0\x0e\xa9\x83"
+"\xea\xb0\x3a\xb0\x0e\xad\x83\xeb\xf0\x3a"
+"\xc0\x0e\xb1\x83\xec\x30\x3b\xd0\x0e\xb5"
+"\x83\xed\x70\x3b\xe0\x0e\xb9\x83\xee\xb0"
+"\x3b\xf0\x0e\xbd\x83\xef\xf0\x3b\x00\x0f"
+"\xc1\x83\xf0\x30\x3c\x10\x0f\xc5\x83\xf1"
+"\x70\x3c\x20\x0f\xc9\x83\xf2\xb0\x3c\x30"
+"\x0f\xcd\x83\xf3\x00\x00\x00"
+"iso88598\0\x0d\x21"
+"\x00\x80\x28\x30\x0a\x90\x02\xa5\x80\x29"
+"\x70\x0a\xa0\x02\xa9\xc0\x35\xb0\x0a\xb0"
+"\x02\xad\x80\x2b\xf0\x0a\xc0\x02\xb1\x80"
+"\x2c\x30\x0b\xd0\x02\xb5\x80\x2d\x70\x0b"
+"\xe0\x02\xb9\xc0\x3d\xb0\x0b\xf0\x02\xbd"
+"\x80\x2f\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00\x70\x01"
+"\x40\x17\xd1\x85\x74\x30\x5d\x50\x17\xd5"
+"\x85\x75\x70\x5d\x60\x17\xd9\x85\x76\xb0"
+"\x5d\x70\x17\xdd\x85\x77\xf0\x5d\x80\x17"
+"\xe1\x85\x78\x30\x5e\x90\x17\xe5\x85\x79"
+"\x70\x5e\xa0\x17\xe9\x85\x7a\x00\x00\x00"
+"\x00\x0e\xe0\x03\x00\x00\x00"
+"iso88599\0\x09\x50"
+"\x1e\xa3\x49\x9b\x46\xad\x9a\xb5\x6b\xd8"
+"\xb2\x69\xdb\xc6\x0d\xa6\xd7\x6f\xe0\xc2"
+"\x89\x1b\x47\xae\x9c\xb9\x73\xe8\xd2\xa9"
+"\x5b\xc7\xae\x9d\xbb\x77\x1f\xe3\xc9\x9b"
+"\x47\xaf\x9e\xbd\x7b\xf8\xf2\xe9\xdb\xc7"
+"\x2f\xe6\xd7\x7f"
+"iso885910\0\x0d\x21"
+"\x04\x81\x44\x20\x12\xa8\x04\x28\x81\x4d"
+"\x70\x0a\xec\x04\x10\x01\x58\x60\x16\xf4"
+"\x05\xad\x80\x5a\xa0\x14\xc0\x02\x05\xc1"
+"\x44\x30\x12\xac\x04\x29\xc1\x4d\x70\x0b"
+"\xf0\x04\x11\x41\x58\x70\x16\xf8\x05\x15"
+"\xe0\x5a\xb0\x14\x00\x04\xc1\x80\x30\x30"
+"\x0c\x10\x03\xc5\x80\x31\xe0\x12\x30\x04"
+"\xc9\x00\x46\xb0\x0c\x58\x04\xcd\x80\x33"
+"\xf0\x0c\x40\x03\x45\x01\x53\x30\x0d\x50"
+"\x03\xd5\x80\x35\x80\x16\x60\x03\x72\x81"
+"\x36\xb0\x0d\x70\x03\xdd\x80\x37\xf0\x0d"
+"\x04\x04\xe1\x80\x38\x30\x0e\x90\x03\xe5"
+"\x80\x39\xf0\x12\x34\x04\xe9\x40\x46\xb0"
+"\x0e\x5c\x04\xed\x80\x3b\xf0\x0e\xc0\x03"
+"\x46\x41\x53\x30\x0f\xd0\x03\xf5\x80\x3d"
+"\x90\x16\xe0\x03\x73\x81\x3e\xb0\x0f\xf0"
+"\x03\xfd\x80\x3f\x80\x13\x00"
+"iso885913\0\x0d\x21"
+"\x1d\xa0\x28\x30\x0a\x90\x02\x1e\xa0\x29"
+"\x70\x0a\x60\x03\xa9\x80\x55\xb0\x0a\xb0"
+"\x02\xad\x80\x2b\x60\x0c\xc0\x02\xb1\x80"
+"\x2c\x30\x0b\x70\x80\xb5\x80\x2d\x70\x0b"
+"\xe0\x03\xb9\xc0\x55\xb0\x0b\xf0\x02\xbd"
+"\x80\x2f\x60\x0e\x10\x04\x2e\x01\x40\x60"
+"\x10\x10\x03\xc5\x00\x46\x20\x11\x30\x04"
+"\xc9\x40\x5e\x60\x11\x88\x04\x36\x81\x4a"
+"\xb0\x13\x80\x05\x43\x41\x51\x30\x0d\x30"
+"\x05\xd5\x80\x35\x70\x0d\xc8\x05\x41\x81"
+"\x56\xa0\x16\x70\x03\x7b\x41\x5f\xf0\x0d"
+"\x14\x04\x2f\x41\x40\x70\x10\x90\x03\xe5"
+"\x40\x46\x30\x11\x34\x04\xe9\x80\x5e\x70"
+"\x11\x8c\x04\x37\xc1\x4a\xc0\x13\x84\x05"
+"\x44\x81\x51\x30\x0f\x34\x05\xf5\x80\x3d"
+"\x70\x0f\xcc\x05\x42\xc1\x56\xb0\x16\xf0"
+"\x03\x7c\x81\x5f\x90\x01\x00"
+"iso885914\0\x0c\x21"
+"\x02\x7e\xc0\x8c\x02\x85\xb0\x10\x14\xfc"
+"\x29\x00\xf4\xa9\x40\xd0\x2c\x78\x79\xd0"
+"\x0a\x5c\x01\x5e\xf0\xf0\x1f\x1e\x24\x84"
+"\x04\x20\x10\xe4\x6c\x81\x95\x08\xf4\x57"
+"\x7e\xd0\x80\xf9\x79\x40\xe8\x0a\x7d\x98"
+"\x00\x06\xc1\x40\x18\x0c\x03\x62\x50\x0c"
+"\x8c\xc1\x31\x40\x06\xc9\x40\x19\x2c\x03"
+"\x66\xd0\x0c\x9c\xc1\x33\xa0\x0b\xd1\x40"
+"\x1a\x4c\x03\x6a\x50\x0d\xac\x81\x9a\xc0"
+"\x06\xd9\x40\x1b\x6c\x03\x6e\xd0\x0d\xec"
+"\xc2\x37\x00\x07\xe1\x40\x1c\x8c\x03\x72"
+"\x50\x0e\xcc\xc1\x39\x40\x07\xe9\x40\x1d"
+"\xac\x03\x76\xd0\x0e\xdc\xc1\x3b\xa8\x0b"
+"\xf1\x40\x1e\xcc\x03\x7a\x50\x0f\xec\xc1"
+"\x9a\xc0\x07\xf9\x40\x1f\xec\x03\x7e\xd0"
+"\x0f\xee\xc2\x3f\x00"
+"iso885916\0\x0d\x21"
+"\x04\x41\x41\x10\x14\xb0\x82\x1e\x20\x58"
+"\x70\x0a\x84\x05\xa9\x00\x86\xb0\x0a\xe4"
+"\x05\xad\x80\x5e\xb0\x17\xc0\x02\xb1\x00"
+"\x43\x20\x14\xf4\x05\x1d\xa0\x2d\x70\x0b"
+"\xf8\x05\x0d\x41\x86\xb0\x0b\x48\x05\x53"
+"\x01\x5e\xc0\x17\x00\x03\xc1\x80\x30\x20"
+"\x10\x10\x03\x06\x81\x31\x70\x0c\x20\x03"
+"\xc9\x80\x32\xb0\x0c\x30\x03\xcd\x80\x33"
+"\xf0\x0c\x40\x04\x43\x81\x34\x30\x0d\x50"
+"\x03\x50\x81\x35\xa0\x15\xc0\x05\xd9\x80"
+"\x36\xb0\x0d\x70\x03\x18\x81\x86\xf0\x0d"
+"\x80\x03\xe1\x80\x38\x30\x10\x90\x03\x07"
+"\x81\x39\x70\x0e\xa0\x03\xe9\x80\x3a\xb0"
+"\x0e\xb0\x03\xed\x80\x3b\xf0\x0e\x44\x04"
+"\x44\x81\x3c\x30\x0f\xd0\x03\x51\x81\x3d"
+"\xb0\x15\xc4\x05\xf9\x80\x3e\xb0\x0f\xf0"
+"\x03\x19\xc1\x86\xf0\x0f\x00"
+;
+
+
+'i','s','o','8','8','5','9','1',0,
+8,128,
+'i','s','o','8','8','5','9','2',0,
+10, 33,
+0x04, 0x61, 0x1b, 0x14, 0x29, 0x3d, 0x69, 0x75, 0x0a, 0x2a,
+0x60, 0x79, 0x45, 0x56, 0x5e, 0xad, 0xf4, 0xb5, 0x17, 0x2c,
+0x05, 0x6d, 0x2b, 0x14, 0x2d, 0x3e, 0x6d, 0x75, 0x2c, 0x2e,
+0x61, 0x7d, 0x55, 0x96, 0x5e, 0xdd, 0xfa, 0xc5, 0x17, 0x55,
+0xc1, 0x08, 0x23, 0x10, 0x31, 0x39, 0x19, 0x74, 0x0c, 0x43,
+0xc9, 0x60, 0xb4, 0x8c, 0x46, 0xcd, 0x38, 0xe3, 0x10, 0x44,
+0x43, 0x1d, 0x35, 0x0d, 0x35, 0x50, 0x59, 0x73, 0x0d, 0x56,
+0x6e, 0x69, 0x03, 0x17, 0x37, 0xdd, 0x88, 0xf5, 0x4d, 0x55,
+0xe1, 0x88, 0x33, 0x10, 0x39, 0x3a, 0x1d, 0x74, 0x4e, 0x43,
+0xe9, 0x64, 0xb4, 0xce, 0x46, 0xed, 0xb8, 0xf3, 0x50, 0x44,
+0x44, 0x21, 0x35, 0x0f, 0x3d, 0x51, 0xd9, 0x73, 0x4f, 0x56,
+0x6f, 0xe9, 0x13, 0x17, 0x3f, 0xfd, 0x8c, 0x95, 0x2d,
+'i','s','o','8','8','5','9','3',0,
+10, 33,
+0x26, 0x61, 0x3b, 0x0a, 0x29, 0x00, 0x90, 0x74, 0x0a, 0x2a,
+0x30, 0x79, 0xe5, 0x11, 0x4d, 0xad, 0x00, 0xb0, 0x17, 0x2c,
+0x27, 0xc9, 0x32, 0x0b, 0x2d, 0xb5, 0x94, 0x74, 0x0b, 0x2e,
+0x31, 0x7d, 0xf5, 0x51, 0x4d, 0xbd, 0x00, 0xc0, 0x17, 0x30,
+0xc1, 0x08, 0x03, 0x00, 0x31, 0x0a, 0x21, 0x74, 0x0c, 0x32,
+0xc9, 0x28, 0xb3, 0x0c, 0x33, 0xcd, 0x38, 0xf3, 0x0c, 0x00,
+0xd1, 0x48, 0x33, 0x0d, 0x35, 0x20, 0x59, 0x73, 0x0d, 0x47,
+0xd9, 0x68, 0xb3, 0x0d, 0x37, 0x6c, 0x71, 0xf5, 0x0d, 0x38,
+0xe1, 0x88, 0x03, 0x00, 0x39, 0x0b, 0x25, 0x74, 0x0e, 0x3a,
+0xe9, 0xa8, 0xb3, 0x0e, 0x3b, 0xed, 0xb8, 0xf3, 0x0e, 0x00,
+0xf1, 0xc8, 0x33, 0x0f, 0x3d, 0x21, 0xd9, 0x73, 0x4f, 0x47,
+0xf9, 0xe8, 0xb3, 0x0f, 0x3f, 0x6d, 0x75, 0x95, 0x2d,
+'i','s','o','8','8','5','9','4',0,
+10, 33,
+0x04, 0xe1, 0x64, 0x15, 0x29, 0x28, 0xed, 0x74, 0x0a, 0x2a,
+0x60, 0x49, 0x24, 0x92, 0x59, 0xad, 0xf4, 0xf5, 0x0a, 0x2c,
+0x05, 0x6d, 0x7b, 0x15, 0x2d, 0x29, 0xf1, 0x74, 0x2c, 0x2e,
+0x61, 0x4d, 0x34, 0xd2, 0x59, 0x4a, 0xf9, 0xb5, 0x14, 0x40,
+0xc1, 0x08, 0x33, 0x0c, 0x31, 0xc5, 0x18, 0xe3, 0x12, 0x43,
+0xc9, 0x60, 0xb4, 0x8c, 0x45, 0xcd, 0x38, 0xa3, 0x12, 0x44,
+0x45, 0x31, 0x65, 0x13, 0x35, 0xd5, 0x58, 0x73, 0x0d, 0x36,
+0x72, 0x69, 0xb3, 0x0d, 0x37, 0x68, 0xa9, 0xf5, 0x4d, 0x40,
+0xe1, 0x88, 0x33, 0x0e, 0x39, 0xe5, 0x98, 0xf3, 0x52, 0x43,
+0xe9, 0x64, 0xb4, 0xce, 0x45, 0xed, 0xb8, 0xb3, 0x52, 0x44,
+0x46, 0x35, 0x75, 0x13, 0x3d, 0xf5, 0xd8, 0x73, 0x0f, 0x3e,
+0x73, 0xe9, 0xb3, 0x0f, 0x3f, 0x69, 0xad, 0x95, 0x2d,
+'i','s','o','8','8','5','9','5',0,
+14, 33,
+0x01, 0x84, 0x00, 0x30, 0x40, 0x10, 0x10, 0x05, 0x84, 0x01,
+0x70, 0x40, 0x20, 0x10, 0x09, 0x84, 0x02, 0xb0, 0x40, 0x30,
+0x10, 0xad, 0x80, 0x03, 0xf0, 0x40, 0x40, 0x10, 0x11, 0x84,
+0x04, 0x30, 0x41, 0x50, 0x10, 0x15, 0x84, 0x05, 0x70, 0x41,
+0x60, 0x10, 0x19, 0x84, 0x06, 0xb0, 0x41, 0x70, 0x10, 0x1d,
+0x84, 0x07, 0xf0, 0x41, 0x80, 0x10, 0x21, 0x84, 0x08, 0x30,
+0x42, 0x90, 0x10, 0x25, 0x84, 0x09, 0x70, 0x42, 0xa0, 0x10,
+0x29, 0x84, 0x0a, 0xb0, 0x42, 0xb0, 0x10, 0x2d, 0x84, 0x0b,
+0xf0, 0x42, 0xc0, 0x10, 0x31, 0x84, 0x0c, 0x30, 0x43, 0xd0,
+0x10, 0x35, 0x84, 0x0d, 0x70, 0x43, 0xe0, 0x10, 0x39, 0x84,
+0x0e, 0xb0, 0x43, 0xf0, 0x10, 0x3d, 0x84, 0x0f, 0xf0, 0x43,
+0x00, 0x11, 0x41, 0x84, 0x10, 0x30, 0x44, 0x10, 0x11, 0x45,
+0x84, 0x11, 0x70, 0x44, 0x20, 0x11, 0x49, 0x84, 0x12, 0xb0,
+0x44, 0x30, 0x11, 0x4d, 0x84, 0x13, 0xf0, 0x44, 0x58, 0x84,
+0x51, 0x84, 0x14, 0x30, 0x45, 0x50, 0x11, 0x55, 0x84, 0x15,
+0x70, 0x45, 0x60, 0x11, 0x59, 0x84, 0x16, 0xb0, 0x45, 0x70,
+0x11, 0xa7, 0x80, 0x17, 0xf0, 0x45, 0x00,
+'i','s','o','8','8','5','9','6',0,
+11, 33,
+0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xdc, 0x0a, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x86, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0x18, 0x00, 0x21, 0x16, 0xf1, 0x88, 0x48, 0x5c,
+0x62, 0x13, 0x9c, 0x18, 0xc5, 0x29, 0x56, 0xf1, 0x8a, 0x58,
+0xdc, 0x62, 0x17, 0xbc, 0x18, 0xc6, 0x31, 0x96, 0xf1, 0x8c,
+0x68, 0x5c, 0x63, 0x1b, 0xdc, 0x18, 0xc7, 0x39, 0xd6, 0x31,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x41, 0x16,
+0xf2, 0x90, 0x88, 0x5c, 0x64, 0x23, 0x1c, 0x19, 0xc9, 0x49,
+0x56, 0xf2, 0x92, 0x98, 0xdc, 0x64, 0x27, 0x3c, 0x19, 0xca,
+0x51, 0x96, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+'i','s','o','8','8','5','9','7',0,
+14, 33,
+0x18, 0x60, 0x06, 0x30, 0x0a, 0xb0, 0x82, 0xaf, 0xa0, 0x29,
+0x70, 0x0a, 0xa0, 0x02, 0xa9, 0x80, 0xde, 0xb0, 0x0a, 0xb0,
+0x02, 0xad, 0x00, 0x00, 0x50, 0x01, 0xc0, 0x02, 0xb1, 0x80,
+0x2c, 0x30, 0x0b, 0x10, 0x0e, 0x85, 0x83, 0xe1, 0x70, 0x0b,
+0x20, 0x0e, 0x89, 0x83, 0xe2, 0xb0, 0x0b, 0x30, 0x0e, 0xbd,
+0x80, 0xe3, 0xf0, 0x38, 0x40, 0x0e, 0x91, 0x83, 0xe4, 0x30,
+0x39, 0x50, 0x0e, 0x95, 0x83, 0xe5, 0x70, 0x39, 0x60, 0x0e,
+0x99, 0x83, 0xe6, 0xb0, 0x39, 0x70, 0x0e, 0x9d, 0x83, 0xe7,
+0xf0, 0x39, 0x80, 0x0e, 0xa1, 0x03, 0x00, 0x30, 0x3a, 0x90,
+0x0e, 0xa5, 0x83, 0xe9, 0x70, 0x3a, 0xa0, 0x0e, 0xa9, 0x83,
+0xea, 0xb0, 0x3a, 0xb0, 0x0e, 0xad, 0x83, 0xeb, 0xf0, 0x3a,
+0xc0, 0x0e, 0xb1, 0x83, 0xec, 0x30, 0x3b, 0xd0, 0x0e, 0xb5,
+0x83, 0xed, 0x70, 0x3b, 0xe0, 0x0e, 0xb9, 0x83, 0xee, 0xb0,
+0x3b, 0xf0, 0x0e, 0xbd, 0x83, 0xef, 0xf0, 0x3b, 0x00, 0x0f,
+0xc1, 0x83, 0xf0, 0x30, 0x3c, 0x10, 0x0f, 0xc5, 0x83, 0xf1,
+0x70, 0x3c, 0x20, 0x0f, 0xc9, 0x83, 0xf2, 0xb0, 0x3c, 0x30,
+0x0f, 0xcd, 0x83, 0xf3, 0x00, 0x00, 0x00,
+'i','s','o','8','8','5','9','8',0,
+14, 33,
+0x00, 0x80, 0x28, 0x30, 0x0a, 0x90, 0x02, 0xa5, 0x80, 0x29,
+0x70, 0x0a, 0xa0, 0x02, 0xa9, 0xc0, 0x35, 0xb0, 0x0a, 0xb0,
+0x02, 0xad, 0x80, 0x2b, 0xf0, 0x0a, 0xc0, 0x02, 0xb1, 0x80,
+0x2c, 0x30, 0x0b, 0xd0, 0x02, 0xb5, 0x80, 0x2d, 0x70, 0x0b,
+0xe0, 0x02, 0xb9, 0xc0, 0x3d, 0xb0, 0x0b, 0xf0, 0x02, 0xbd,
+0x80, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01,
+0x40, 0x17, 0xd1, 0x85, 0x74, 0x30, 0x5d, 0x50, 0x17, 0xd5,
+0x85, 0x75, 0x70, 0x5d, 0x60, 0x17, 0xd9, 0x85, 0x76, 0xb0,
+0x5d, 0x70, 0x17, 0xdd, 0x85, 0x77, 0xf0, 0x5d, 0x80, 0x17,
+0xe1, 0x85, 0x78, 0x30, 0x5e, 0x90, 0x17, 0xe5, 0x85, 0x79,
+0x70, 0x5e, 0xa0, 0x17, 0xe9, 0x85, 0x7a, 0x00, 0x00, 0x00,
+0x00, 0x0e, 0xe0, 0x03, 0x00, 0x00, 0x00,
+'i','s','o','8','8','5','9','9',0,
+9, 80,
+0x1e, 0xa3, 0x49, 0x9b, 0x46, 0xad, 0x9a, 0xb5, 0x6b, 0xd8,
+0xb2, 0x69, 0xdb, 0xc6, 0x0d, 0xa6, 0xd7, 0x6f, 0xe0, 0xc2,
+0x89, 0x1b, 0x47, 0xae, 0x9c, 0xb9, 0x73, 0xe8, 0xd2, 0xa9,
+0x5b, 0xc7, 0xae, 0x9d, 0xbb, 0x77, 0x1f, 0xe3, 0xc9, 0x9b,
+0x47, 0xaf, 0x9e, 0xbd, 0x7b, 0xf8, 0xf2, 0xe9, 0xdb, 0xc7,
+0x2f, 0xe6, 0xd7, 0x7f,
+'i','s','o','8','8','5','9','1','0',0,
+14, 33,
+0x04, 0x81, 0x44, 0x20, 0x12, 0xa8, 0x04, 0x28, 0x81, 0x4d,
+0x70, 0x0a, 0xec, 0x04, 0x10, 0x01, 0x58, 0x60, 0x16, 0xf4,
+0x05, 0xad, 0x80, 0x5a, 0xa0, 0x14, 0xc0, 0x02, 0x05, 0xc1,
+0x44, 0x30, 0x12, 0xac, 0x04, 0x29, 0xc1, 0x4d, 0x70, 0x0b,
+0xf0, 0x04, 0x11, 0x41, 0x58, 0x70, 0x16, 0xf8, 0x05, 0x15,
+0xe0, 0x5a, 0xb0, 0x14, 0x00, 0x04, 0xc1, 0x80, 0x30, 0x30,
+0x0c, 0x10, 0x03, 0xc5, 0x80, 0x31, 0xe0, 0x12, 0x30, 0x04,
+0xc9, 0x00, 0x46, 0xb0, 0x0c, 0x58, 0x04, 0xcd, 0x80, 0x33,
+0xf0, 0x0c, 0x40, 0x03, 0x45, 0x01, 0x53, 0x30, 0x0d, 0x50,
+0x03, 0xd5, 0x80, 0x35, 0x80, 0x16, 0x60, 0x03, 0x72, 0x81,
+0x36, 0xb0, 0x0d, 0x70, 0x03, 0xdd, 0x80, 0x37, 0xf0, 0x0d,
+0x04, 0x04, 0xe1, 0x80, 0x38, 0x30, 0x0e, 0x90, 0x03, 0xe5,
+0x80, 0x39, 0xf0, 0x12, 0x34, 0x04, 0xe9, 0x40, 0x46, 0xb0,
+0x0e, 0x5c, 0x04, 0xed, 0x80, 0x3b, 0xf0, 0x0e, 0xc0, 0x03,
+0x46, 0x41, 0x53, 0x30, 0x0f, 0xd0, 0x03, 0xf5, 0x80, 0x3d,
+0x90, 0x16, 0xe0, 0x03, 0x73, 0x81, 0x3e, 0xb0, 0x0f, 0xf0,
+0x03, 0xfd, 0x80, 0x3f, 0x80, 0x13, 0x00,
+'i','s','o','8','8','5','9','1','3',0,
+14, 33,
+0x1d, 0xa0, 0x28, 0x30, 0x0a, 0x90, 0x02, 0x1e, 0xa0, 0x29,
+0x70, 0x0a, 0x60, 0x03, 0xa9, 0x80, 0x55, 0xb0, 0x0a, 0xb0,
+0x02, 0xad, 0x80, 0x2b, 0x60, 0x0c, 0xc0, 0x02, 0xb1, 0x80,
+0x2c, 0x30, 0x0b, 0x70, 0x80, 0xb5, 0x80, 0x2d, 0x70, 0x0b,
+0xe0, 0x03, 0xb9, 0xc0, 0x55, 0xb0, 0x0b, 0xf0, 0x02, 0xbd,
+0x80, 0x2f, 0x60, 0x0e, 0x10, 0x04, 0x2e, 0x01, 0x40, 0x60,
+0x10, 0x10, 0x03, 0xc5, 0x00, 0x46, 0x20, 0x11, 0x30, 0x04,
+0xc9, 0x40, 0x5e, 0x60, 0x11, 0x88, 0x04, 0x36, 0x81, 0x4a,
+0xb0, 0x13, 0x80, 0x05, 0x43, 0x41, 0x51, 0x30, 0x0d, 0x30,
+0x05, 0xd5, 0x80, 0x35, 0x70, 0x0d, 0xc8, 0x05, 0x41, 0x81,
+0x56, 0xa0, 0x16, 0x70, 0x03, 0x7b, 0x41, 0x5f, 0xf0, 0x0d,
+0x14, 0x04, 0x2f, 0x41, 0x40, 0x70, 0x10, 0x90, 0x03, 0xe5,
+0x40, 0x46, 0x30, 0x11, 0x34, 0x04, 0xe9, 0x80, 0x5e, 0x70,
+0x11, 0x8c, 0x04, 0x37, 0xc1, 0x4a, 0xc0, 0x13, 0x84, 0x05,
+0x44, 0x81, 0x51, 0x30, 0x0f, 0x34, 0x05, 0xf5, 0x80, 0x3d,
+0x70, 0x0f, 0xcc, 0x05, 0x42, 0xc1, 0x56, 0xb0, 0x16, 0xf0,
+0x03, 0x7c, 0x81, 0x5f, 0x90, 0x01, 0x00,
+'i','s','o','8','8','5','9','1','4',0,
+13, 33,
+0x02, 0x7e, 0xc0, 0x8c, 0x02, 0x85, 0xb0, 0x10, 0x14, 0xfc,
+0x29, 0x00, 0xf4, 0xa9, 0x40, 0xd0, 0x2c, 0x78, 0x79, 0xd0,
+0x0a, 0x5c, 0x01, 0x5e, 0xf0, 0xf0, 0x1f, 0x1e, 0x24, 0x84,
+0x04, 0x20, 0x10, 0xe4, 0x6c, 0x81, 0x95, 0x08, 0xf4, 0x57,
+0x7e, 0xd0, 0x80, 0xf9, 0x79, 0x40, 0xe8, 0x0a, 0x7d, 0x98,
+0x00, 0x06, 0xc1, 0x40, 0x18, 0x0c, 0x03, 0x62, 0x50, 0x0c,
+0x8c, 0xc1, 0x31, 0x40, 0x06, 0xc9, 0x40, 0x19, 0x2c, 0x03,
+0x66, 0xd0, 0x0c, 0x9c, 0xc1, 0x33, 0xa0, 0x0b, 0xd1, 0x40,
+0x1a, 0x4c, 0x03, 0x6a, 0x50, 0x0d, 0xac, 0x81, 0x9a, 0xc0,
+0x06, 0xd9, 0x40, 0x1b, 0x6c, 0x03, 0x6e, 0xd0, 0x0d, 0xec,
+0xc2, 0x37, 0x00, 0x07, 0xe1, 0x40, 0x1c, 0x8c, 0x03, 0x72,
+0x50, 0x0e, 0xcc, 0xc1, 0x39, 0x40, 0x07, 0xe9, 0x40, 0x1d,
+0xac, 0x03, 0x76, 0xd0, 0x0e, 0xdc, 0xc1, 0x3b, 0xa8, 0x0b,
+0xf1, 0x40, 0x1e, 0xcc, 0x03, 0x7a, 0x50, 0x0f, 0xec, 0xc1,
+0x9a, 0xc0, 0x07, 0xf9, 0x40, 0x1f, 0xec, 0x03, 0x7e, 0xd0,
+0x0f, 0xee, 0xc2, 0x3f, 0x00,
+'i','s','o','8','8','5','9','1','6',0,
+14, 33,
+0x04, 0x41, 0x41, 0x10, 0x14, 0xb0, 0x82, 0x1e, 0x20, 0x58,
+0x70, 0x0a, 0x84, 0x05, 0xa9, 0x00, 0x86, 0xb0, 0x0a, 0xe4,
+0x05, 0xad, 0x80, 0x5e, 0xb0, 0x17, 0xc0, 0x02, 0xb1, 0x00,
+0x43, 0x20, 0x14, 0xf4, 0x05, 0x1d, 0xa0, 0x2d, 0x70, 0x0b,
+0xf8, 0x05, 0x0d, 0x41, 0x86, 0xb0, 0x0b, 0x48, 0x05, 0x53,
+0x01, 0x5e, 0xc0, 0x17, 0x00, 0x03, 0xc1, 0x80, 0x30, 0x20,
+0x10, 0x10, 0x03, 0x06, 0x81, 0x31, 0x70, 0x0c, 0x20, 0x03,
+0xc9, 0x80, 0x32, 0xb0, 0x0c, 0x30, 0x03, 0xcd, 0x80, 0x33,
+0xf0, 0x0c, 0x40, 0x04, 0x43, 0x81, 0x34, 0x30, 0x0d, 0x50,
+0x03, 0x50, 0x81, 0x35, 0xa0, 0x15, 0xc0, 0x05, 0xd9, 0x80,
+0x36, 0xb0, 0x0d, 0x70, 0x03, 0x18, 0x81, 0x86, 0xf0, 0x0d,
+0x80, 0x03, 0xe1, 0x80, 0x38, 0x30, 0x10, 0x90, 0x03, 0x07,
+0x81, 0x39, 0x70, 0x0e, 0xa0, 0x03, 0xe9, 0x80, 0x3a, 0xb0,
+0x0e, 0xb0, 0x03, 0xed, 0x80, 0x3b, 0xf0, 0x0e, 0x44, 0x04,
+0x44, 0x81, 0x3c, 0x30, 0x0f, 0xd0, 0x03, 0x51, 0x81, 0x3d,
+0xb0, 0x15, 0xc4, 0x05, 0xf9, 0x80, 0x3e, 0xb0, 0x0f, 0xf0,
+0x03, 0x19, 0xc1, 0x86, 0xf0, 0x0f, 0x00,
diff --git a/src/locale/tolower_l.c b/src/locale/tolower_l.c
new file mode 100644 (file)
index 0000000..ba27791
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int tolower_l(int c, locale_t l)
+{
+       return tolower(c);
+}
diff --git a/src/locale/toupper_l.c b/src/locale/toupper_l.c
new file mode 100644 (file)
index 0000000..73f2f39
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int toupper_l(int c, locale_t l)
+{
+       return toupper(c);
+}
diff --git a/src/locale/wcscoll.c b/src/locale/wcscoll.c
new file mode 100644 (file)
index 0000000..cdbce1c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+/* FIXME: stub */
+int wcscoll(const wchar_t *l, const wchar_t *r)
+{
+       return wcscmp(l, r);
+}
diff --git a/src/locale/wcsxfrm.c b/src/locale/wcsxfrm.c
new file mode 100644 (file)
index 0000000..5f76e5a
--- /dev/null
@@ -0,0 +1,12 @@
+#include <wchar.h>
+
+/* collate only by code points */
+size_t wcsxfrm(wchar_t *dest, const wchar_t *src, size_t n)
+{
+       size_t l = wcslen(src);
+       if (l >= n) {
+               wmemcpy(dest, src, n-1);
+               dest[n-1] = 0;
+       } else wcscpy(dest, src);
+       return l;
+}
diff --git a/src/malloc/DESIGN b/src/malloc/DESIGN
new file mode 100644 (file)
index 0000000..58b0523
--- /dev/null
@@ -0,0 +1,22 @@
+
+
+In principle, this memory allocator is roughly equivalent to Doug
+Lea's dlmalloc with fine-grained locking.
+
+
+
+malloc:
+
+Uses a freelist binned by chunk size, with a bitmap to optimize
+searching for the smallest non-empty bin which can satisfy an
+allocation. If no free chunks are available, it creates a new chunk of
+the requested size and attempts to merge it with any existing free
+chunk immediately below the newly created chunk.
+
+Whether the chunk was obtained from a bin or newly created, it's
+likely to be larger than the requested allocation. malloc always
+finishes its work by passing the new chunk to realloc, which will
+split it into two chunks and free the tail portion.
+
+
+
diff --git a/src/malloc/__brk.c b/src/malloc/__brk.c
new file mode 100644 (file)
index 0000000..e3b3af3
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdint.h>
+#include "syscall.h"
+
+uintptr_t __brk(uintptr_t newbrk)
+{
+       return syscall1(__NR_brk, newbrk);
+}
diff --git a/src/malloc/__simple_malloc.c b/src/malloc/__simple_malloc.c
new file mode 100644 (file)
index 0000000..49b74c8
--- /dev/null
@@ -0,0 +1,44 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <errno.h>
+#include "libc.h"
+
+uintptr_t __brk(uintptr_t);
+
+#define ALIGN 16
+
+void *__simple_malloc(size_t n)
+{
+       static uintptr_t cur, brk;
+       uintptr_t base, new;
+       static int lock;
+       size_t align=1;
+
+       if (n < SIZE_MAX - ALIGN)
+               while (align<n && align<ALIGN)
+                       align += align;
+       n = n + align - 1 & -align;
+
+       LOCK(&lock);
+       if (!cur) cur = brk = __brk(0)+16;
+       if (n > SIZE_MAX - brk) goto fail;
+
+       base = cur + align-1 & -align;
+       if (base+n > brk) {
+               new = base+n + PAGE_SIZE-1 & -PAGE_SIZE;
+               if (__brk(new) != new) goto fail;
+               brk = new;
+       }
+       cur = base+n;
+       UNLOCK(&lock);
+
+       return (void *)base;
+
+fail:
+       UNLOCK(&lock);
+       errno = ENOMEM;
+       return 0;
+}
+
+weak_alias(__simple_malloc, malloc);
diff --git a/src/malloc/calloc.c b/src/malloc/calloc.c
new file mode 100644 (file)
index 0000000..9d57456
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+void *calloc(size_t m, size_t n)
+{
+       void *p;
+       size_t *z;
+       if (n && m > (size_t)-1/n) {
+               errno = ENOMEM;
+               return 0;
+       }
+       n *= m;
+       p = malloc(n);
+       if (!p) return 0;
+       /* Only do this for non-mmapped chunks */
+       if (((size_t *)p)[-1] & 7) {
+               /* Only write words that are not already zero */
+               m = (n + sizeof *z - 1)/sizeof *z;
+               for (z=p; m; m--, z++) if (*z) *z=0;
+       }
+       return p;
+}
diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c
new file mode 100644 (file)
index 0000000..d9a30fe
--- /dev/null
@@ -0,0 +1,515 @@
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include "libc.h"
+#include "atomic.h"
+#include "pthread_impl.h"
+
+uintptr_t __brk(uintptr_t);
+void *__mmap(void *, size_t, int, int, int, off_t);
+int __munmap(void *, size_t);
+void *__mremap(void *, size_t, size_t, int, ...);
+int __madvise(void *, size_t, int);
+
+struct chunk {
+       size_t data[1];
+       struct chunk *next;
+       struct chunk *prev;
+};
+
+struct bin {
+       int lock[2];
+       struct chunk *head;
+       struct chunk *tail;
+};
+
+static struct {
+       uintptr_t brk;
+       size_t *heap;
+       uint64_t binmap;
+       struct bin bins[64];
+       int brk_lock[2];
+       int free_lock[2];
+} mal;
+
+
+#define SIZE_ALIGN (4*sizeof(size_t))
+#define SIZE_MASK (-SIZE_ALIGN)
+#define OVERHEAD (2*sizeof(size_t))
+#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN)
+#define DONTCARE 16
+#define RECLAIM 163840
+
+#define CHUNK_SIZE(c) ((c)->data[0] & SIZE_MASK)
+#define CHUNK_PSIZE(c) ((c)->data[-1] & SIZE_MASK)
+#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c)))
+#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c)))
+#define MEM_TO_CHUNK(p) (struct chunk *)((size_t *)p - 1)
+#define CHUNK_TO_MEM(c) (void *)((c)->data+1)
+#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head))
+
+#define C_INUSE  ((size_t)1)
+#define C_FLAGS  ((size_t)3)
+#define C_SIZE   SIZE_MASK
+
+#define IS_MMAPPED(c) !((c)->data[0] & (C_INUSE))
+
+
+/* Synchronization tools */
+
+static void lock(volatile int *lk)
+{
+       if (!libc.threads_minus_1) return;
+       while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
+}
+
+static void unlock(volatile int *lk)
+{
+       if (!libc.threads_minus_1) return;
+       a_store(lk, 0);
+       if (lk[1]) __wake(lk, 1, 1);
+}
+
+static void lock_bin(int i)
+{
+       if (libc.threads_minus_1)
+               lock(mal.bins[i].lock);
+       if (!mal.bins[i].head)
+               mal.bins[i].head = mal.bins[i].tail = BIN_TO_CHUNK(i);
+}
+
+static void unlock_bin(int i)
+{
+       if (!libc.threads_minus_1) return;
+       unlock(mal.bins[i].lock);
+}
+
+static int first_set(uint64_t x)
+{
+#if 1
+       return a_ctz_64(x);
+#else
+       static const char debruijn64[64] = {
+               0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
+               62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
+               63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
+               51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
+       };
+       static const char debruijn32[32] = {
+               0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
+               31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
+       };
+       if (sizeof(long) < 8) {
+               uint32_t y = x;
+               if (!y) {
+                       y = x>>32;
+                       return 32 + debruijn32[(y&-y)*0x076be629 >> 27];
+               }
+               return debruijn32[(y&-y)*0x076be629 >> 27];
+       }
+       return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
+#endif
+}
+
+static int bin_index(size_t x)
+{
+       x = x / SIZE_ALIGN - 1;
+       if (x <= 32) return x;
+       if (x > 0x1c00) return 63;
+       return ((union { float v; uint32_t r; }){ x }.r>>21) - 496;
+}
+
+static int bin_index_up(size_t x)
+{
+       x = x / SIZE_ALIGN - 1;
+       if (x <= 32) return x;
+       return ((union { float v; uint32_t r; }){ x }.r+0x1fffff>>21) - 496;
+}
+
+#if 0
+void __dump_heap(int x)
+{
+       struct chunk *c;
+       int i;
+       for (c = (void *)mal.heap; CHUNK_SIZE(c); c = NEXT_CHUNK(c))
+               fprintf(stderr, "base %p size %zu (%d) flags %d/%d\n",
+                       c, CHUNK_SIZE(c), bin_index(CHUNK_SIZE(c)),
+                       c->data[0] & 15,
+                       NEXT_CHUNK(c)->data[-1] & 15);
+       for (i=0; i<64; i++) {
+               if (mal.bins[i].head != BIN_TO_CHUNK(i) && mal.bins[i].head) {
+                       fprintf(stderr, "bin %d: %p\n", i, mal.bins[i].head);
+                       if (!(mal.binmap & 1ULL<<i))
+                               fprintf(stderr, "missing from binmap!\n");
+               } else if (mal.binmap & 1ULL<<i)
+                       fprintf(stderr, "binmap wrongly contains %d!\n", i);
+       }
+}
+#endif
+
+static struct chunk *expand_heap(size_t n)
+{
+       struct chunk *w;
+       uintptr_t new;
+
+       lock(mal.brk_lock);
+
+       if (n > SIZE_MAX - mal.brk - 2*PAGE_SIZE) goto fail;
+       new = mal.brk + n + SIZE_ALIGN + PAGE_SIZE - 1 & -PAGE_SIZE;
+       n = new - mal.brk;
+
+       if (__brk(new) != new) goto fail;
+
+       w = MEM_TO_CHUNK(new);
+       w->data[-1] = n | C_INUSE;
+       w->data[0] = 0 | C_INUSE;
+
+       w = MEM_TO_CHUNK(mal.brk);
+       w->data[0] = n | C_INUSE;
+       mal.brk = new;
+       
+       unlock(mal.brk_lock);
+
+       return w;
+fail:
+       unlock(mal.brk_lock);
+       return 0;
+}
+
+static int init_malloc()
+{
+       static int init, waiters;
+       int state;
+       struct chunk *c;
+
+       if (init == 2) return 0;
+
+       while ((state=a_swap(&init, 1)) == 1)
+               __wait(&init, &waiters, 1, 1);
+       if (state) {
+               a_store(&init, 2);
+               return 0;
+       }
+
+       mal.brk = __brk(0) + 2*SIZE_ALIGN-1 & -SIZE_ALIGN;
+
+       c = expand_heap(1);
+
+       if (!c) {
+               a_store(&init, 0);
+               if (waiters) __wake(&init, 1, 1);
+               return -1;
+       }
+
+       mal.heap = (void *)c;
+       c->data[-1] = 0 | C_INUSE;
+       free(CHUNK_TO_MEM(c));
+
+       a_store(&init, 2);
+       if (waiters) __wake(&init, -1, 1);
+       return 0;
+}
+
+static int adjust_size(size_t *n)
+{
+       /* Result of pointer difference must fit in ptrdiff_t. */
+       if (*n > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE) {
+               errno = ENOMEM;
+               return -1;
+       }
+       *n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
+       return 0;
+}
+
+static void unbin(struct chunk *c, int i)
+{
+       if (c->prev == c->next)
+               a_and_64(&mal.binmap, ~(1ULL<<i));
+       c->prev->next = c->next;
+       c->next->prev = c->prev;
+       c->data[0] |= C_INUSE;
+       NEXT_CHUNK(c)->data[-1] |= C_INUSE;
+}
+
+static int alloc_fwd(struct chunk *c)
+{
+       int i;
+       size_t k;
+       while (!((k=c->data[0]) & C_INUSE)) {
+               i = bin_index(k);
+               lock_bin(i);
+               if (c->data[0] == k) {
+                       unbin(c, i);
+                       unlock_bin(i);
+                       return 1;
+               }
+               unlock_bin(i);
+       }
+       return 0;
+}
+
+static int alloc_rev(struct chunk *c)
+{
+       int i;
+       size_t k;
+       while (!((k=c->data[-1]) & C_INUSE)) {
+               i = bin_index(k);
+               lock_bin(i);
+               if (c->data[-1] == k) {
+                       unbin(PREV_CHUNK(c), i);
+                       unlock_bin(i);
+                       return 1;
+               }
+               unlock_bin(i);
+       }
+       return 0;
+}
+
+
+/* pretrim - trims a chunk _prior_ to removing it from its bin.
+ * Must be called with i as the ideal bin for size n, j the bin
+ * for the _free_ chunk self, and bin j locked. */
+static int pretrim(struct chunk *self, size_t n, int i, int j)
+{
+       size_t n1;
+       struct chunk *next, *split;
+
+       /* We cannot pretrim if it would require re-binning. */
+       if (j < 40) return 0;
+       if (j < i+3) {
+               if (j != 63) return 0;
+               n1 = CHUNK_SIZE(self);
+               if (n1-n <= MMAP_THRESHOLD) return 0;
+       } else {
+               n1 = CHUNK_SIZE(self);
+       }
+       if (bin_index(n1-n) != j) return 0;
+
+       next = NEXT_CHUNK(self);
+       split = (void *)((char *)self + n);
+
+       split->prev = self->prev;
+       split->next = self->next;
+       split->prev->next = split;
+       split->next->prev = split;
+       split->data[-1] = n | C_INUSE;
+       split->data[0] = n1-n;
+       next->data[-1] = n1-n;
+       self->data[0] = n | C_INUSE;
+       return 1;
+}
+
+static void trim(struct chunk *self, size_t n)
+{
+       size_t n1 = CHUNK_SIZE(self);
+       struct chunk *next, *split;
+
+       if (n >= n1 - DONTCARE) return;
+
+       next = NEXT_CHUNK(self);
+       split = (void *)((char *)self + n);
+
+       split->data[-1] = n | C_INUSE;
+       split->data[0] = n1-n | C_INUSE;
+       next->data[-1] = n1-n | C_INUSE;
+       self->data[0] = n | C_INUSE;
+
+       free(CHUNK_TO_MEM(split));
+}
+
+void *malloc(size_t n)
+{
+       struct chunk *c;
+       int i, j;
+
+       if (!n || adjust_size(&n) < 0) return 0;
+
+       if (n > MMAP_THRESHOLD) {
+               size_t len = n + PAGE_SIZE - 1 & -PAGE_SIZE;
+               char *base = __mmap(0, len, PROT_READ|PROT_WRITE,
+                       MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+               if (base == (void *)-1) return 0;
+               c = (void *)(base + SIZE_ALIGN - sizeof(size_t));
+               c->data[0] = len - (SIZE_ALIGN - sizeof(size_t));
+               c->data[-1] = SIZE_ALIGN - sizeof(size_t);
+               return CHUNK_TO_MEM(c);
+       }
+
+       i = bin_index_up(n);
+       for (;;) {
+               uint64_t mask = mal.binmap & -(1ULL<<i);
+               if (!mask) {
+                       init_malloc();
+                       c = expand_heap(n);
+                       if (!c) return 0;
+                       if (alloc_rev(c)) {
+                               struct chunk *x = c;
+                               c = PREV_CHUNK(c);
+                               NEXT_CHUNK(x)->data[-1] = c->data[0] =
+                                       x->data[0] + CHUNK_SIZE(c);
+                       }
+                       break;
+               }
+               j = first_set(mask);
+               lock_bin(j);
+               c = mal.bins[j].head;
+               if (c != BIN_TO_CHUNK(j) && j == bin_index(c->data[0])) {
+                       if (!pretrim(c, n, i, j)) unbin(c, j);
+                       unlock_bin(j);
+                       break;
+               }
+               unlock_bin(j);
+       }
+
+       /* Now patch up in case we over-allocated */
+       trim(c, n);
+
+       return CHUNK_TO_MEM(c);
+}
+
+void *realloc(void *p, size_t n)
+{
+       struct chunk *self, *next;
+       size_t n0, n1;
+       void *new;
+
+       if (!p) return malloc(n);
+       else if (!n) return free(p), (void *)0;
+
+       if (adjust_size(&n) < 0) return 0;
+
+       self = MEM_TO_CHUNK(p);
+       n1 = n0 = CHUNK_SIZE(self);
+
+       if (IS_MMAPPED(self)) {
+               size_t extra = self->data[-1];
+               char *base = (char *)self - extra;
+               size_t oldlen = n0 + extra;
+               size_t newlen = n + extra;
+               if (newlen < PAGE_SIZE && (new = malloc(n))) {
+                       memcpy(new, p, n-OVERHEAD);
+                       free(p);
+                       return new;
+               }
+               newlen = (newlen + PAGE_SIZE-1) & -PAGE_SIZE;
+               if (oldlen == newlen) return p;
+               base = __mremap(base, oldlen, newlen, MREMAP_MAYMOVE);
+               if (base == (void *)-1)
+                       return newlen < oldlen ? p : 0;
+               self = (void *)(base + extra);
+               self->data[0] = newlen - extra;
+               return CHUNK_TO_MEM(self);
+       }
+
+       next = NEXT_CHUNK(self);
+
+       /* Merge adjacent chunks if we need more space. This is not
+        * a waste of time even if we fail to get enough space, because our
+        * subsequent call to free would otherwise have to do the merge. */
+       if (n > n1 && alloc_fwd(next)) {
+               n1 += CHUNK_SIZE(next);
+               next = NEXT_CHUNK(next);
+       }
+       /* FIXME: find what's wrong here and reenable it..? */
+       if (0 && n > n1 && alloc_rev(self)) {
+               self = PREV_CHUNK(self);
+               n1 += CHUNK_SIZE(self);
+       }
+       self->data[0] = n1 | C_INUSE;
+       next->data[-1] = n1 | C_INUSE;
+
+       /* If we got enough space, split off the excess and return */
+       if (n <= n1) {
+               //memmove(CHUNK_TO_MEM(self), p, n0-OVERHEAD);
+               trim(self, n);
+               return CHUNK_TO_MEM(self);
+       }
+
+       /* As a last resort, allocate a new chunk and copy to it. */
+       new = malloc(n-OVERHEAD);
+       if (!new) return 0;
+       memcpy(new, p, n0-OVERHEAD);
+       free(CHUNK_TO_MEM(self));
+       return new;
+}
+
+void free(void *p)
+{
+       struct chunk *self = MEM_TO_CHUNK(p);
+       struct chunk *next;
+       size_t final_size, new_size, size;
+       int reclaim=0;
+       int i;
+
+       if (!p) return;
+
+       if (IS_MMAPPED(self)) {
+               size_t extra = self->data[-1];
+               char *base = (char *)self - extra;
+               size_t len = CHUNK_SIZE(self) + extra;
+               __munmap(base, len);
+               return;
+       }
+
+       final_size = new_size = CHUNK_SIZE(self);
+       next = NEXT_CHUNK(self);
+
+       for (;;) {
+               /* Replace middle of large chunks with fresh zero pages */
+               if (reclaim && (self->data[-1] & next->data[0] & C_INUSE)) {
+                       uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE;
+                       uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE;
+#if 1
+                       __madvise((void *)a, b-a, MADV_DONTNEED);
+#else
+                       __mmap((void *)a, b-a, PROT_READ|PROT_WRITE,
+                               MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+#endif
+               }
+
+               if (self->data[-1] & next->data[0] & C_INUSE) {
+                       self->data[0] = final_size | C_INUSE;
+                       next->data[-1] = final_size | C_INUSE;
+                       i = bin_index(final_size);
+                       lock_bin(i);
+                       lock(mal.free_lock);
+                       if (self->data[-1] & next->data[0] & C_INUSE)
+                               break;
+                       unlock(mal.free_lock);
+                       unlock_bin(i);
+               }
+
+               if (alloc_rev(self)) {
+                       self = PREV_CHUNK(self);
+                       size = CHUNK_SIZE(self);
+                       final_size += size;
+                       if (new_size+size > RECLAIM && (new_size+size^size) > size)
+                               reclaim = 1;
+               }
+
+               if (alloc_fwd(next)) {
+                       size = CHUNK_SIZE(next);
+                       final_size += size;
+                       if (new_size+size > RECLAIM && (new_size+size^size) > size)
+                               reclaim = 1;
+                       next = NEXT_CHUNK(next);
+               }
+       }
+
+       self->data[0] = final_size;
+       next->data[-1] = final_size;
+       unlock(mal.free_lock);
+
+       self->next = BIN_TO_CHUNK(i);
+       self->prev = mal.bins[i].tail;
+       self->next->prev = self;
+       self->prev->next = self;
+
+       if (!(mal.binmap & 1ULL<<i))
+               a_or_64(&mal.binmap, 1ULL<<i);
+
+       unlock_bin(i);
+}
diff --git a/src/malloc/memalign.c b/src/malloc/memalign.c
new file mode 100644 (file)
index 0000000..61f456e
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include <errno.h>
+
+void *memalign(size_t align, size_t len)
+{
+       void *mem;
+       int ret;
+       if ((ret = posix_memalign(&mem, align, len))) {
+               errno = ret;
+               return 0;
+       }
+       return mem;
+}
diff --git a/src/malloc/posix_memalign.c b/src/malloc/posix_memalign.c
new file mode 100644 (file)
index 0000000..ef86260
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+
+/* This function should work with most dlmalloc-like chunk bookkeeping
+ * systems, but it's only guaranteed to work with the native implementation
+ * used in this library. */
+
+int posix_memalign(void **res, size_t align, size_t len)
+{
+       unsigned char *mem, *new, *end;
+       size_t header, footer;
+
+       if ((align & -align) != align) return EINVAL;
+       if (len > SIZE_MAX - align) return ENOMEM;
+
+       if (align <= 4*sizeof(size_t)) {
+               if (!(mem = malloc(len)))
+                       return errno;
+               *res = mem;
+               return 0;
+       }
+
+       if (!(mem = malloc(len + align-1)))
+               return errno;
+
+       header = ((size_t *)mem)[-1];
+       end = mem + (header & -8);
+       footer = ((size_t *)end)[-2];
+       new = (void *)((uintptr_t)mem + align-1 & -align);
+
+       if (!(header & 7)) {
+               ((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem);
+               ((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem);
+               *res = new;
+               return 0;
+       }
+
+       ((size_t *)mem)[-1] = header&7 | new-mem;
+       ((size_t *)new)[-2] = footer&7 | new-mem;
+       ((size_t *)new)[-1] = header&7 | end-new;
+       ((size_t *)end)[-2] = footer&7 | end-new;
+
+       if (new != mem) free(mem);
+       *res = new;
+       return 0;
+}
diff --git a/src/math/__fpclassify.c b/src/math/__fpclassify.c
new file mode 100644 (file)
index 0000000..1605110
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdint.h>
+#include <math.h>
+
+int __fpclassify(double __x)
+{
+       union {
+               double __d;
+               __uint64_t __i;
+       } __y = { __x };
+       int __ee = __y.__i>>52 & 0x7ff;
+       if (!__ee) return __y.__i<<1 ? FP_SUBNORMAL : FP_ZERO;
+       if (__ee==0x7ff) return __y.__i<<12 ? FP_NAN : FP_INFINITE;
+       return FP_NORMAL;
+}
diff --git a/src/math/__fpclassifyf.c b/src/math/__fpclassifyf.c
new file mode 100644 (file)
index 0000000..bf59d0d
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdint.h>
+#include <math.h>
+
+int __fpclassifyf(float __x)
+{
+       union {
+               float __f;
+               __uint32_t __i;
+       } __y = { __x };
+       int __ee = __y.__i>>23 & 0xff;
+       if (!__ee) return __y.__i<<1 ? FP_SUBNORMAL : FP_ZERO;
+       if (__ee==0xff) return __y.__i<<9 ? FP_NAN : FP_INFINITE;
+       return FP_NORMAL;
+}
diff --git a/src/math/__fpclassifyl.c b/src/math/__fpclassifyl.c
new file mode 100644 (file)
index 0000000..4f93bef
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdint.h>
+#include <math.h>
+
+/* FIXME: move this to arch-specific file */
+int __fpclassifyl(long double __x)
+{
+       union {
+               long double __ld;
+               __uint16_t __hw[5];
+               __uint64_t __m;
+       } __y = { __x };
+       int __ee = __y.__hw[4]&0x7fff;
+       if (!__ee) return __y.__m ? FP_SUBNORMAL : FP_ZERO;
+       if (__ee==0x7fff) return __y.__m ? FP_NAN : FP_INFINITE;
+       return FP_NORMAL;
+}
diff --git a/src/math/e_acos.c b/src/math/e_acos.c
new file mode 100644 (file)
index 0000000..e023639
--- /dev/null
@@ -0,0 +1,99 @@
+/* @(#)e_acos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* acos(x)
+ * Method :                  
+ *      acos(x)  = pi/2 - asin(x)
+ *      acos(-x) = pi/2 + asin(x)
+ * For |x|<=0.5
+ *      acos(x) = pi/2 - (x + x*x^2*R(x^2))     (see asin.c)
+ * For x>0.5
+ *      acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
+ *              = 2asin(sqrt((1-x)/2))  
+ *              = 2s + 2s*z*R(z)        ...z=(1-x)/2, s=sqrt(z)
+ *              = 2f + (2c + 2s*z*R(z))
+ *     where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
+ *     for f so that f+c ~ sqrt(z).
+ * For x<-0.5
+ *      acos(x) = pi - 2asin(sqrt((1-|x|)/2))
+ *              = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
+ *
+ * Special cases:
+ *      if x is NaN, return x itself;
+ *      if |x|>1, return NaN with invalid signal.
+ *
+ * Function needed: sqrt
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+one=  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo =  6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pS0 =  1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 =  2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 =  7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 =  3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+double
+acos(double x)
+{
+        double z,p,q,r,w,s,c,df;
+        int32_t hx,ix;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x3ff00000) {    /* |x| >= 1 */
+            uint32_t lx;
+            GET_LOW_WORD(lx,x);
+            if(((ix-0x3ff00000)|lx)==0) {       /* |x|==1 */
+                if(hx>0) return 0.0;            /* acos(1) = 0  */
+                else return pi+2.0*pio2_lo;     /* acos(-1)= pi */
+            }
+            return (x-x)/(x-x);         /* acos(|x|>1) is NaN */
+        }
+        if(ix<0x3fe00000) {     /* |x| < 0.5 */
+            if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+            z = x*x;
+            p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+            q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+            r = p/q;
+            return pio2_hi - (x - (pio2_lo-x*r));
+        } else  if (hx<0) {             /* x < -0.5 */
+            z = (one+x)*0.5;
+            p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+            q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+            s = sqrt(z);
+            r = p/q;
+            w = r*s-pio2_lo;
+            return pi - 2.0*(s+w);
+        } else {                        /* x > 0.5 */
+            z = (one-x)*0.5;
+            s = sqrt(z);
+            df = s;
+            SET_LOW_WORD(df,0);
+            c  = (z-df*df)/(s+df);
+            p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+            q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+            r = p/q;
+            w = r*s+c;
+            return 2.0*(df+w);
+        }
+}
diff --git a/src/math/e_acosf.c b/src/math/e_acosf.c
new file mode 100644 (file)
index 0000000..4c59781
--- /dev/null
@@ -0,0 +1,77 @@
+/* e_acosf.c -- float version of e_acos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3F800000 */
+pi =  3.1415925026e+00, /* 0x40490fda */
+pio2_hi =  1.5707962513e+00, /* 0x3fc90fda */
+pio2_lo =  7.5497894159e-08, /* 0x33a22168 */
+pS0 =  1.6666667163e-01, /* 0x3e2aaaab */
+pS1 = -3.2556581497e-01, /* 0xbea6b090 */
+pS2 =  2.0121252537e-01, /* 0x3e4e0aa8 */
+pS3 = -4.0055535734e-02, /* 0xbd241146 */
+pS4 =  7.9153501429e-04, /* 0x3a4f7f04 */
+pS5 =  3.4793309169e-05, /* 0x3811ef08 */
+qS1 = -2.4033949375e+00, /* 0xc019d139 */
+qS2 =  2.0209457874e+00, /* 0x4001572d */
+qS3 = -6.8828397989e-01, /* 0xbf303361 */
+qS4 =  7.7038154006e-02; /* 0x3d9dc62e */
+
+float
+acosf(float x)
+{
+        float z,p,q,r,w,s,c,df;
+        int32_t hx,ix;
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix==0x3f800000) {            /* |x|==1 */
+            if(hx>0) return 0.0;        /* acos(1) = 0  */
+            else return pi+(float)2.0*pio2_lo;  /* acos(-1)= pi */
+        } else if(ix>0x3f800000) {      /* |x| >= 1 */
+            return (x-x)/(x-x);         /* acos(|x|>1) is NaN */
+        }
+        if(ix<0x3f000000) {     /* |x| < 0.5 */
+            if(ix<=0x23000000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+            z = x*x;
+            p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+            q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+            r = p/q;
+            return pio2_hi - (x - (pio2_lo-x*r));
+        } else  if (hx<0) {             /* x < -0.5 */
+            z = (one+x)*(float)0.5;
+            p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+            q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+            s = sqrtf(z);
+            r = p/q;
+            w = r*s-pio2_lo;
+            return pi - (float)2.0*(s+w);
+        } else {                        /* x > 0.5 */
+            int32_t idf;
+            z = (one-x)*(float)0.5;
+            s = sqrtf(z);
+            df = s;
+            GET_FLOAT_WORD(idf,df);
+            SET_FLOAT_WORD(df,idf&0xfffff000);
+            c  = (z-df*df)/(s+df);
+            p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+            q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+            r = p/q;
+            w = r*s+c;
+            return (float)2.0*(df+w);
+        }
+}
diff --git a/src/math/e_acosh.c b/src/math/e_acosh.c
new file mode 100644 (file)
index 0000000..8b454e7
--- /dev/null
@@ -0,0 +1,59 @@
+
+/* @(#)e_acosh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* acosh(x)
+ * Method :
+ *      Based on 
+ *              acosh(x) = log [ x + sqrt(x*x-1) ]
+ *      we have
+ *              acosh(x) := log(x)+ln2, if x is large; else
+ *              acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
+ *              acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ *      acosh(x) is NaN with signal if x<1.
+ *      acosh(NaN) is NaN without signal.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+one     = 1.0,
+ln2     = 6.93147180559945286227e-01;  /* 0x3FE62E42, 0xFEFA39EF */
+
+double
+acosh(double x)
+{
+        double t;
+        int32_t hx;
+        uint32_t lx;
+        EXTRACT_WORDS(hx,lx,x);
+        if(hx<0x3ff00000) {             /* x < 1 */
+            return (x-x)/(x-x);
+        } else if(hx >=0x41b00000) {    /* x > 2**28 */
+            if(hx >=0x7ff00000) {       /* x is inf of NaN */
+                return x+x;
+            } else 
+                return log(x)+ln2;    /* acosh(huge)=log(2x) */
+        } else if(((hx-0x3ff00000)|lx)==0) {
+            return 0.0;                 /* acosh(1) = 0 */
+        } else if (hx > 0x40000000) {   /* 2**28 > x > 2 */
+            t=x*x;
+            return log(2.0*x-one/(x+sqrt(t-one)));
+        } else {                        /* 1<x<2 */
+            t = x-one;
+            return log1p(t+sqrt(2.0*t+t*t));
+        }
+}
diff --git a/src/math/e_acoshf.c b/src/math/e_acoshf.c
new file mode 100644 (file)
index 0000000..b7f1df6
--- /dev/null
@@ -0,0 +1,45 @@
+/* e_acoshf.c -- float version of e_acosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one     = 1.0,
+ln2     = 6.9314718246e-01;  /* 0x3f317218 */
+
+float
+acoshf(float x)
+{
+        float t;
+        int32_t hx;
+        GET_FLOAT_WORD(hx,x);
+        if(hx<0x3f800000) {             /* x < 1 */
+            return (x-x)/(x-x);
+        } else if(hx >=0x4d800000) {    /* x > 2**28 */
+            if(hx >=0x7f800000) {       /* x is inf of NaN */
+                return x+x;
+            } else
+                return logf(x)+ln2;     /* acosh(huge)=log(2x) */
+        } else if (hx==0x3f800000) {
+            return 0.0;                 /* acosh(1) = 0 */
+        } else if (hx > 0x40000000) {   /* 2**28 > x > 2 */
+            t=x*x;
+            return logf((float)2.0*x-one/(x+sqrtf(t-one)));
+        } else {                        /* 1<x<2 */
+            t = x-one;
+            return log1pf(t+sqrtf((float)2.0*t+t*t));
+        }
+}
diff --git a/src/math/e_asin.c b/src/math/e_asin.c
new file mode 100644 (file)
index 0000000..4bf162a
--- /dev/null
@@ -0,0 +1,109 @@
+
+/* @(#)e_asin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* asin(x)
+ * Method :                  
+ *      Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
+ *      we approximate asin(x) on [0,0.5] by
+ *              asin(x) = x + x*x^2*R(x^2)
+ *      where
+ *              R(x^2) is a rational approximation of (asin(x)-x)/x^3 
+ *      and its remez error is bounded by
+ *              |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
+ *
+ *      For x in [0.5,1]
+ *              asin(x) = pi/2-2*asin(sqrt((1-x)/2))
+ *      Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
+ *      then for x>0.98
+ *              asin(x) = pi/2 - 2*(s+s*z*R(z))
+ *                      = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
+ *      For x<=0.98, let pio4_hi = pio2_hi/2, then
+ *              f = hi part of s;
+ *              c = sqrt(z) - f = (z-f*f)/(s+f)         ...f+c=sqrt(z)
+ *      and
+ *              asin(x) = pi/2 - 2*(s+s*z*R(z))
+ *                      = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
+ *                      = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
+ *
+ * Special cases:
+ *      if x is NaN, return x itself;
+ *      if |x|>1, return NaN with invalid signal.
+ *
+ */
+
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+huge =  1.000e+300,
+pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo =  6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pio4_hi =  7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+        /* coefficient for R(x^2) */
+pS0 =  1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 =  2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 =  7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 =  3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+double
+asin(double x)
+{
+        double t=0.0,w,p,q,c,r,s;
+        int32_t hx,ix;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>= 0x3ff00000) {           /* |x|>= 1 */
+            uint32_t lx;
+            GET_LOW_WORD(lx,x);
+            if(((ix-0x3ff00000)|lx)==0)
+                    /* asin(1)=+-pi/2 with inexact */
+                return x*pio2_hi+x*pio2_lo;     
+            return (x-x)/(x-x);         /* asin(|x|>1) is NaN */   
+        } else if (ix<0x3fe00000) {     /* |x|<0.5 */
+            if(ix<0x3e400000) {         /* if |x| < 2**-27 */
+                if(huge+x>one) return x;/* return x with inexact if x!=0*/
+            } else 
+                t = x*x;
+                p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+                q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+                w = p/q;
+                return x+x*w;
+        }
+        /* 1> |x|>= 0.5 */
+        w = one-fabs(x);
+        t = w*0.5;
+        p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+        q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+        s = sqrt(t);
+        if(ix>=0x3FEF3333) {    /* if |x| > 0.975 */
+            w = p/q;
+            t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+        } else {
+            w  = s;
+            SET_LOW_WORD(w,0);
+            c  = (t-w*w)/(s+w);
+            r  = p/q;
+            p  = 2.0*s*r-(pio2_lo-2.0*c);
+            q  = pio4_hi-2.0*w;
+            t  = pio4_hi-(p-q);
+        }    
+        if(hx>0) return t; else return -t;    
+}
diff --git a/src/math/e_asinf.c b/src/math/e_asinf.c
new file mode 100644 (file)
index 0000000..9c69397
--- /dev/null
@@ -0,0 +1,80 @@
+/* e_asinf.c -- float version of e_asin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3F800000 */
+huge =  1.000e+30,
+pio2_hi =  1.5707962513e+00, /* 0x3fc90fda */
+pio2_lo =  7.5497894159e-08, /* 0x33a22168 */
+pio4_hi =  7.8539818525e-01, /* 0x3f490fdb */
+       /* coefficient for R(x^2) */
+pS0 =  1.6666667163e-01, /* 0x3e2aaaab */
+pS1 = -3.2556581497e-01, /* 0xbea6b090 */
+pS2 =  2.0121252537e-01, /* 0x3e4e0aa8 */
+pS3 = -4.0055535734e-02, /* 0xbd241146 */
+pS4 =  7.9153501429e-04, /* 0x3a4f7f04 */
+pS5 =  3.4793309169e-05, /* 0x3811ef08 */
+qS1 = -2.4033949375e+00, /* 0xc019d139 */
+qS2 =  2.0209457874e+00, /* 0x4001572d */
+qS3 = -6.8828397989e-01, /* 0xbf303361 */
+qS4 =  7.7038154006e-02; /* 0x3d9dc62e */
+
+float
+asinf(float x)
+{
+       float t=0.0,w,p,q,c,r,s;
+       int32_t hx,ix;
+       GET_FLOAT_WORD(hx,x);
+       ix = hx&0x7fffffff;
+       if(ix==0x3f800000) {
+               /* asin(1)=+-pi/2 with inexact */
+           return x*pio2_hi+x*pio2_lo;
+       } else if(ix> 0x3f800000) {     /* |x|>= 1 */
+           return (x-x)/(x-x);         /* asin(|x|>1) is NaN */
+       } else if (ix<0x3f000000) {     /* |x|<0.5 */
+           if(ix<0x32000000) {         /* if |x| < 2**-27 */
+               if(huge+x>one) return x;/* return x with inexact if x!=0*/
+           } else
+               t = x*x;
+               p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+               q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+               w = p/q;
+               return x+x*w;
+       }
+       /* 1> |x|>= 0.5 */
+       w = one-fabsf(x);
+       t = w*(float)0.5;
+       p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+       q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+       s = sqrtf(t);
+       if(ix>=0x3F79999A) {    /* if |x| > 0.975 */
+           w = p/q;
+           t = pio2_hi-((float)2.0*(s+s*w)-pio2_lo);
+       } else {
+           int32_t iw;
+           w  = s;
+           GET_FLOAT_WORD(iw,w);
+           SET_FLOAT_WORD(w,iw&0xfffff000);
+           c  = (t-w*w)/(s+w);
+           r  = p/q;
+           p  = (float)2.0*s*r-(pio2_lo-(float)2.0*c);
+           q  = pio4_hi-(float)2.0*w;
+           t  = pio4_hi-(p-q);
+       }
+       if(hx>0) return t; else return -t;
+}
diff --git a/src/math/e_atan2.c b/src/math/e_atan2.c
new file mode 100644 (file)
index 0000000..dd02116
--- /dev/null
@@ -0,0 +1,120 @@
+
+/* @(#)e_atan2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* atan2(y,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,
+ *
+ * Special cases:
+ *
+ *      ATAN2((anything), NaN ) is NaN;
+ *      ATAN2(NAN , (anything) ) is NaN;
+ *      ATAN2(+-0, +(anything but NaN)) is +-0  ;
+ *      ATAN2(+-0, -(anything but NaN)) is +-pi ;
+ *      ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
+ *      ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
+ *      ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
+ *      ATAN2(+-INF,+INF ) is +-pi/4 ;
+ *      ATAN2(+-INF,-INF ) is +-3pi/4;
+ *      ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ *
+ * 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 <math.h>
+#include "math_private.h"
+
+static const double
+tiny  = 1.0e-300,
+zero  = 0.0,
+pi_o_4  = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+pi_o_2  = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+pi      = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
+pi_lo   = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+double
+atan2(double y, double x)
+{
+        double z;
+        int32_t k,m,hx,hy,ix,iy;
+        uint32_t lx,ly;
+
+        EXTRACT_WORDS(hx,lx,x);
+        ix = hx&0x7fffffff;
+        EXTRACT_WORDS(hy,ly,y);
+        iy = hy&0x7fffffff;
+        if(((ix|((lx|-lx)>>31))>0x7ff00000)||
+           ((iy|((ly|-ly)>>31))>0x7ff00000))    /* x or y is NaN */
+           return x+y;
+        if(((hx-0x3ff00000)|lx)==0) return atan(y);   /* x=1.0 */
+        m = ((hy>>31)&1)|((hx>>30)&2);  /* 2*sign(x)+sign(y) */
+
+    /* when y = 0 */
+        if((iy|ly)==0) {
+            switch(m) {
+                case 0: 
+                case 1: return y;       /* atan(+-0,+anything)=+-0 */
+                case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
+                case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+            }
+        }
+    /* when x = 0 */
+        if((ix|lx)==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
+            
+    /* when x is INF */
+        if(ix==0x7ff00000) {
+            if(iy==0x7ff00000) {
+                switch(m) {
+                    case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
+                    case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+                    case 2: return  3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+                    case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+                }
+            } else {
+                switch(m) {
+                    case 0: return  zero  ;     /* atan(+...,+INF) */
+                    case 1: return -zero  ;     /* atan(-...,+INF) */
+                    case 2: return  pi+tiny  ;  /* atan(+...,-INF) */
+                    case 3: return -pi-tiny  ;  /* atan(-...,-INF) */
+                }
+            }
+        }
+    /* when y is INF */
+        if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+    /* compute y/x */
+        k = (iy-ix)>>20;
+        if(k > 60) z=pi_o_2+0.5*pi_lo;  /* |y/x| >  2**60 */
+        else if(hx<0&&k<-60) z=0.0;     /* |y|/x < -2**60 */
+        else z=atan(fabs(y/x));         /* safe to do y/x */
+        switch (m) {
+            case 0: return       z  ;   /* atan(+,+) */
+            case 1: {
+                      uint32_t zh;
+                      GET_HIGH_WORD(zh,z);
+                      SET_HIGH_WORD(z,zh ^ 0x80000000);
+                    }
+                    return       z  ;   /* atan(-,+) */
+            case 2: return  pi-(z-pi_lo);/* atan(+,-) */
+            default: /* case 3 */
+                    return  (z-pi_lo)-pi;/* atan(-,-) */
+        }
+}
diff --git a/src/math/e_atan2f.c b/src/math/e_atan2f.c
new file mode 100644 (file)
index 0000000..535e10a
--- /dev/null
@@ -0,0 +1,93 @@
+/* e_atan2f.c -- float version of e_atan2.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+tiny  = 1.0e-30,
+zero  = 0.0,
+pi_o_4  = 7.8539818525e-01, /* 0x3f490fdb */
+pi_o_2  = 1.5707963705e+00, /* 0x3fc90fdb */
+pi      = 3.1415927410e+00, /* 0x40490fdb */
+pi_lo   = -8.7422776573e-08; /* 0xb3bbbd2e */
+
+float
+atan2f(float y, float x)
+{
+        float z;
+        int32_t k,m,hx,hy,ix,iy;
+
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        GET_FLOAT_WORD(hy,y);
+        iy = hy&0x7fffffff;
+        if((ix>0x7f800000)||
+           (iy>0x7f800000))     /* x or y is NaN */
+           return x+y;
+        if(hx==0x3f800000) return atanf(y);   /* x=1.0 */
+        m = ((hy>>31)&1)|((hx>>30)&2);  /* 2*sign(x)+sign(y) */
+
+    /* when y = 0 */
+        if(iy==0) {
+            switch(m) {
+                case 0:
+                case 1: return y;       /* atan(+-0,+anything)=+-0 */
+                case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
+                case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+            }
+        }
+    /* when x = 0 */
+        if(ix==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
+
+    /* when x is INF */
+        if(ix==0x7f800000) {
+            if(iy==0x7f800000) {
+                switch(m) {
+                    case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
+                    case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+                    case 2: return  (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+                    case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+                }
+            } else {
+                switch(m) {
+                    case 0: return  zero  ;     /* atan(+...,+INF) */
+                    case 1: return -zero  ;     /* atan(-...,+INF) */
+                    case 2: return  pi+tiny  ;  /* atan(+...,-INF) */
+                    case 3: return -pi-tiny  ;  /* atan(-...,-INF) */
+                }
+            }
+        }
+    /* when y is INF */
+        if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+    /* compute y/x */
+        k = (iy-ix)>>23;
+        if(k > 60) z=pi_o_2+(float)0.5*pi_lo;   /* |y/x| >  2**60 */
+        else if(hx<0&&k<-60) z=0.0;     /* |y|/x < -2**60 */
+        else z=atanf(fabsf(y/x));       /* safe to do y/x */
+        switch (m) {
+            case 0: return       z  ;   /* atan(+,+) */
+            case 1: {
+                      uint32_t zh;
+                      GET_FLOAT_WORD(zh,z);
+                      SET_FLOAT_WORD(z,zh ^ 0x80000000);
+                    }
+                    return       z  ;   /* atan(-,+) */
+            case 2: return  pi-(z-pi_lo);/* atan(+,-) */
+            default: /* case 3 */
+                    return  (z-pi_lo)-pi;/* atan(-,-) */
+        }
+}
diff --git a/src/math/e_atanh.c b/src/math/e_atanh.c
new file mode 100644 (file)
index 0000000..45f1c96
--- /dev/null
@@ -0,0 +1,59 @@
+
+/* @(#)e_atanh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* atanh(x)
+ * Method :
+ *    1.Reduced x to positive by atanh(-x) = -atanh(x)
+ *    2.For x>=0.5
+ *                  1              2x                          x
+ *      atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ *                  2             1 - x                      1 - x
+ *      
+ *      For x<0.5
+ *      atanh(x) = 0.5*log1p(2x+2x*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.
+ *
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one = 1.0, huge = 1e300;
+static const double zero = 0.0;
+
+double
+atanh(double x)
+{
+        double t;
+        int32_t hx,ix;
+        uint32_t lx;
+        EXTRACT_WORDS(hx,lx,x);
+        ix = hx&0x7fffffff;
+        if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
+            return (x-x)/(x-x);
+        if(ix==0x3ff00000) 
+            return x/zero;
+        if(ix<0x3e300000&&(huge+x)>zero) return x;      /* x<2**-28 */
+        SET_HIGH_WORD(x,ix);
+        if(ix<0x3fe00000) {             /* x < 0.5 */
+            t = x+x;
+            t = 0.5*log1p(t+t*x/(one-x));
+        } else 
+            t = 0.5*log1p((x+x)/(one-x));
+        if(hx>=0) return t; else return -t;
+}
diff --git a/src/math/e_atanhf.c b/src/math/e_atanhf.c
new file mode 100644 (file)
index 0000000..7356cfc
--- /dev/null
@@ -0,0 +1,42 @@
+/* e_atanhf.c -- float version of e_atanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one = 1.0, huge = 1e30;
+
+static const float zero = 0.0;
+
+float
+atanhf(float x)
+{
+        float t;
+        int32_t hx,ix;
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if (ix>0x3f800000)              /* |x|>1 */
+            return (x-x)/(x-x);
+        if(ix==0x3f800000)
+            return x/zero;
+        if(ix<0x31800000&&(huge+x)>zero) return x;      /* x<2**-28 */
+        SET_FLOAT_WORD(x,ix);
+        if(ix<0x3f000000) {             /* x < 0.5 */
+            t = x+x;
+            t = (float)0.5*log1pf(t+t*x/(one-x));
+        } else
+            t = (float)0.5*log1pf((x+x)/(one-x));
+        if(hx>=0) return t; else return -t;
+}
diff --git a/src/math/e_cosh.c b/src/math/e_cosh.c
new file mode 100644 (file)
index 0000000..ad425bd
--- /dev/null
@@ -0,0 +1,82 @@
+
+/* @(#)e_cosh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* cosh(x)
+ * Method : 
+ * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
+ *      1. Replace x by |x| (cosh(x) = cosh(-x)). 
+ *      2. 
+ *                                                      [ exp(x) - 1 ]^2 
+ *          0        <= x <= ln2/2  :  cosh(x) := 1 + -------------------
+ *                                                         2*exp(x)
+ *
+ *                                                exp(x) +  1/exp(x)
+ *          ln2/2    <= x <= 22     :  cosh(x) := -------------------
+ *                                                        2
+ *          22       <= x <= lnovft :  cosh(x) := exp(x)/2 
+ *          lnovft   <= x <= ln2ovft:  cosh(x) := exp(x/2)/2 * exp(x/2)
+ *          ln2ovft  <  x           :  cosh(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ *      cosh(x) is |x| if x is +INF, -INF, or NaN.
+ *      only cosh(0)=1 is exact for finite x.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one = 1.0, half=0.5, huge = 1.0e300;
+
+double
+cosh(double x)
+{
+        double t,w;
+        int32_t ix;
+        uint32_t lx;
+
+    /* High word of |x|. */
+        GET_HIGH_WORD(ix,x);
+        ix &= 0x7fffffff;
+
+    /* x is INF or NaN */
+        if(ix>=0x7ff00000) return x*x;  
+
+    /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+        if(ix<0x3fd62e43) {
+            t = expm1(fabs(x));
+            w = one+t;
+            if (ix<0x3c800000) return w;        /* cosh(tiny) = 1 */
+            return one+(t*t)/(w+w);
+        }
+
+    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+        if (ix < 0x40360000) {
+                t = exp(fabs(x));
+                return half*t+half/t;
+        }
+
+    /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+        if (ix < 0x40862E42)  return half*exp(fabs(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+        GET_LOW_WORD(lx,x);
+        if (ix<0x408633CE ||
+              ((ix==0x408633ce)&&(lx<=(uint32_t)0x8fb9f87d))) {
+            w = exp(half*fabs(x));
+            t = half*w;
+            return t*w;
+        }
+
+    /* |x| > overflowthresold, cosh(x) overflow */
+        return huge*huge;
+}
diff --git a/src/math/e_coshf.c b/src/math/e_coshf.c
new file mode 100644 (file)
index 0000000..6db1088
--- /dev/null
@@ -0,0 +1,59 @@
+/* e_coshf.c -- float version of e_cosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one = 1.0, half=0.5, huge = 1.0e30;
+
+float
+coshf(float x)
+{
+        float t,w;
+        int32_t ix;
+
+        GET_FLOAT_WORD(ix,x);
+        ix &= 0x7fffffff;
+
+    /* x is INF or NaN */
+        if(ix>=0x7f800000) return x*x;
+
+    /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+        if(ix<0x3eb17218) {
+            t = expm1f(fabsf(x));
+            w = one+t;
+            if (ix<0x24000000) return w;        /* cosh(tiny) = 1 */
+            return one+(t*t)/(w+w);
+        }
+
+    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+        if (ix < 0x41b00000) {
+                t = expf(fabsf(x));
+                return half*t+half/t;
+        }
+
+    /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+        if (ix < 0x42b17180)  return half*expf(fabsf(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+        if (ix<=0x42b2d4fc) {
+            w = expf(half*fabsf(x));
+            t = half*w;
+            return t*w;
+        }
+
+    /* |x| > overflowthresold, cosh(x) overflow */
+        return huge*huge;
+}
diff --git a/src/math/e_exp.c b/src/math/e_exp.c
new file mode 100644 (file)
index 0000000..66107b9
--- /dev/null
@@ -0,0 +1,155 @@
+
+/* @(#)e_exp.c 1.6 04/04/22 */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ *   1. Argument reduction:
+ *      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ *      Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2.  
+ *
+ *      Here r will be represented as r = hi-lo for better 
+ *      accuracy.
+ *
+ *   2. Approximation of exp(r) by a special rational function on
+ *      the interval [0,0.34658]:
+ *      Write
+ *          R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ *      We use a special Remes algorithm on [0,0.34658] to generate 
+ *      a polynomial of degree 5 to approximate R. The maximum error 
+ *      of this polynomial approximation is bounded by 2**-59. In
+ *      other words,
+ *          R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ *      (where z=r*r, and the values of P1 to P5 are listed below)
+ *      and
+ *          |                  5          |     -59
+ *          | 2.0+P1*z+...+P5*z   -  R(z) | <= 2 
+ *          |                             |
+ *      The computation of exp(r) thus becomes
+ *                             2*r
+ *              exp(r) = 1 + -------
+ *                            R - r
+ *                                 r*R1(r)      
+ *                     = 1 + r + ----------- (for better accuracy)
+ *                                2 - R1(r)
+ *      where
+ *                               2       4             10
+ *              R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+ *      
+ *   3. Scale back to obtain exp(x):
+ *      From step 1, we have
+ *         exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ *      exp(INF) is INF, exp(NaN) is NaN;
+ *      exp(-INF) is 0, and
+ *      for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *      For IEEE double 
+ *          if x >  7.09782712893383973096e+02 then exp(x) overflow
+ *          if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * 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 <math.h>
+#include "math_private.h"
+
+static const double
+one     = 1.0,
+halF[2] = {0.5,-0.5,},
+huge    = 1.0e+300,
+twom1000= 9.33263618503218878990e-302,     /* 2**-1000=0x01700000,0*/
+o_threshold=  7.09782712893383973096e+02,  /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02,  /* 0xc0874910, 0xD52D3051 */
+ln2HI[2]   ={ 6.93147180369123816490e-01,  /* 0x3fe62e42, 0xfee00000 */
+             -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */
+ln2LO[2]   ={ 1.90821492927058770002e-10,  /* 0x3dea39ef, 0x35793c76 */
+             -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
+invln2 =  1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5   =  4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
+
+
+double
+exp(double x) /* default IEEE double exp */
+{
+        double y,hi=0.0,lo=0.0,c,t;
+        int32_t k=0,xsb;
+        uint32_t hx;
+
+        GET_HIGH_WORD(hx,x);
+        xsb = (hx>>31)&1;               /* sign bit of x */
+        hx &= 0x7fffffff;               /* high word of |x| */
+
+    /* filter out non-finite argument */
+        if(hx >= 0x40862E42) {                  /* if |x|>=709.78... */
+            if(hx>=0x7ff00000) {
+                uint32_t lx;
+                GET_LOW_WORD(lx,x);
+                if(((hx&0xfffff)|lx)!=0)
+                     return x+x;                /* NaN */
+                else return (xsb==0)? x:0.0;    /* exp(+-inf)={inf,0} */
+            }
+            if(x > o_threshold) return huge*huge; /* overflow */
+            if(x < u_threshold) return twom1000*twom1000; /* underflow */
+        }
+
+    /* argument reduction */
+        if(hx > 0x3fd62e42) {           /* if  |x| > 0.5 ln2 */ 
+            if(hx < 0x3FF0A2B2) {       /* and |x| < 1.5 ln2 */
+                hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+            } else {
+                k  = (int)(invln2*x+halF[xsb]);
+                t  = k;
+                hi = x - t*ln2HI[0];    /* t*ln2HI is exact here */
+                lo = t*ln2LO[0];
+            }
+            x  = hi - lo;
+        } 
+        else if(hx < 0x3e300000)  {     /* when |x|<2**-28 */
+            if(huge+x>one) return one+x;/* trigger inexact */
+        }
+        else k = 0;
+
+    /* x is now in primary range */
+        t  = x*x;
+        c  = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+        if(k==0)        return one-((x*c)/(c-2.0)-x); 
+        else            y = one-((lo-(x*c)/(2.0-c))-hi);
+        if(k >= -1021) {
+            uint32_t hy;
+            GET_HIGH_WORD(hy,y);
+            SET_HIGH_WORD(y,hy+(k<<20));        /* add k to y's exponent */
+            return y;
+        } else {
+            uint32_t hy;
+            GET_HIGH_WORD(hy,y);
+            SET_HIGH_WORD(y,hy+((k+1000)<<20)); /* add k to y's exponent */
+            return y*twom1000;
+        }
+}
diff --git a/src/math/e_expf.c b/src/math/e_expf.c
new file mode 100644 (file)
index 0000000..99818ed
--- /dev/null
@@ -0,0 +1,91 @@
+/* e_expf.c -- float version of e_exp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one     = 1.0,
+halF[2] = {0.5,-0.5,},
+huge    = 1.0e+30,
+twom100 = 7.8886090522e-31,      /* 2**-100=0x0d800000 */
+o_threshold=  8.8721679688e+01,  /* 0x42b17180 */
+u_threshold= -1.0397208405e+02,  /* 0xc2cff1b5 */
+ln2HI[2]   ={ 6.9313812256e-01,         /* 0x3f317180 */
+             -6.9313812256e-01,},       /* 0xbf317180 */
+ln2LO[2]   ={ 9.0580006145e-06,         /* 0x3717f7d1 */
+             -9.0580006145e-06,},       /* 0xb717f7d1 */
+invln2 =  1.4426950216e+00,             /* 0x3fb8aa3b */
+P1   =  1.6666667163e-01, /* 0x3e2aaaab */
+P2   = -2.7777778450e-03, /* 0xbb360b61 */
+P3   =  6.6137559770e-05, /* 0x388ab355 */
+P4   = -1.6533901999e-06, /* 0xb5ddea0e */
+P5   =  4.1381369442e-08; /* 0x3331bb4c */
+
+float
+expf(float x) /* default IEEE double exp */
+{
+        float y,hi=0.0,lo=0.0,c,t;
+        int32_t k=0,xsb;
+        uint32_t hx;
+
+        GET_FLOAT_WORD(hx,x);
+        xsb = (hx>>31)&1;               /* sign bit of x */
+        hx &= 0x7fffffff;               /* high word of |x| */
+
+    /* filter out non-finite argument */
+        if(hx >= 0x42b17218) {                  /* if |x|>=88.721... */
+            if(hx>0x7f800000)
+                 return x+x;                    /* NaN */
+            if(hx==0x7f800000)
+                return (xsb==0)? x:0.0;         /* exp(+-inf)={inf,0} */
+            if(x > o_threshold) return huge*huge; /* overflow */
+            if(x < u_threshold) return twom100*twom100; /* underflow */
+        }
+
+    /* argument reduction */
+        if(hx > 0x3eb17218) {           /* if  |x| > 0.5 ln2 */
+            if(hx < 0x3F851592) {       /* and |x| < 1.5 ln2 */
+                hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+            } else {
+                k  = invln2*x+halF[xsb];
+                t  = k;
+                hi = x - t*ln2HI[0];    /* t*ln2HI is exact here */
+                lo = t*ln2LO[0];
+            }
+            x  = hi - lo;
+        }
+        else if(hx < 0x31800000)  {     /* when |x|<2**-28 */
+            if(huge+x>one) return one+x;/* trigger inexact */
+        }
+        else k = 0;
+
+    /* x is now in primary range */
+        t  = x*x;
+        c  = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+        if(k==0)        return one-((x*c)/(c-(float)2.0)-x);
+        else            y = one-((lo-(x*c)/((float)2.0-c))-hi);
+        if(k >= -125) {
+            uint32_t hy;
+            GET_FLOAT_WORD(hy,y);
+            SET_FLOAT_WORD(y,hy+(k<<23));       /* add k to y's exponent */
+            return y;
+        } else {
+            uint32_t hy;
+            GET_FLOAT_WORD(hy,y);
+            SET_FLOAT_WORD(y,hy+((k+100)<<23)); /* add k to y's exponent */
+            return y*twom100;
+        }
+}
diff --git a/src/math/e_fmod.c b/src/math/e_fmod.c
new file mode 100644 (file)
index 0000000..99afe48
--- /dev/null
@@ -0,0 +1,129 @@
+
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* 
+ * fmod(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one = 1.0, Zero[] = {0.0, -0.0,};
+
+double
+fmod(double x, double y)
+{
+        int32_t n,hx,hy,hz,ix,iy,sx,i;
+        uint32_t lx,ly,lz;
+
+        EXTRACT_WORDS(hx,lx,x);
+        EXTRACT_WORDS(hy,ly,y);
+        sx = hx&0x80000000;             /* sign of x */
+        hx ^=sx;                /* |x| */
+        hy &= 0x7fffffff;       /* |y| */
+
+    /* purge off exception values */
+        if((hy|ly)==0||(hx>=0x7ff00000)||       /* y=0,or x not finite */
+          ((hy|((ly|-ly)>>31))>0x7ff00000))     /* or y is NaN */
+            return (x*y)/(x*y);
+        if(hx<=hy) {
+            if((hx<hy)||(lx<ly)) return x;      /* |x|<|y| return x */
+            if(lx==ly) 
+                return Zero[(uint32_t)sx>>31]; /* |x|=|y| return x*0*/
+        }
+
+    /* determine ix = ilogb(x) */
+        if(hx<0x00100000) {     /* subnormal x */
+            if(hx==0) {
+                for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+            } else {
+                for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+            }
+        } else ix = (hx>>20)-1023;
+
+    /* determine iy = ilogb(y) */
+        if(hy<0x00100000) {     /* subnormal y */
+            if(hy==0) {
+                for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+            } else {
+                for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+            }
+        } else iy = (hy>>20)-1023;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+        if(ix >= -1022) 
+            hx = 0x00100000|(0x000fffff&hx);
+        else {          /* subnormal x, shift x to normal */
+            n = -1022-ix;
+            if(n<=31) {
+                hx = (hx<<n)|(lx>>(32-n));
+                lx <<= n;
+            } else {
+                hx = lx<<(n-32);
+                lx = 0;
+            }
+        }
+        if(iy >= -1022) 
+            hy = 0x00100000|(0x000fffff&hy);
+        else {          /* subnormal y, shift y to normal */
+            n = -1022-iy;
+            if(n<=31) {
+                hy = (hy<<n)|(ly>>(32-n));
+                ly <<= n;
+            } else {
+                hy = ly<<(n-32);
+                ly = 0;
+            }
+        }
+
+    /* fix point fmod */
+        n = ix - iy;
+        while(n--) {
+            hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+            if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+            else {
+                if((hz|lz)==0)          /* return sign(x)*0 */
+                    return Zero[(uint32_t)sx>>31];
+                hx = hz+hz+(lz>>31); lx = lz+lz;
+            }
+        }
+        hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+        if(hz>=0) {hx=hz;lx=lz;}
+
+    /* convert back to floating value and restore the sign */
+        if((hx|lx)==0)                  /* return sign(x)*0 */
+            return Zero[(uint32_t)sx>>31];
+        while(hx<0x00100000) {          /* normalize x */
+            hx = hx+hx+(lx>>31); lx = lx+lx;
+            iy -= 1;
+        }
+        if(iy>= -1022) {        /* normalize output */
+            hx = ((hx-0x00100000)|((iy+1023)<<20));
+            INSERT_WORDS(x,hx|sx,lx);
+        } else {                /* subnormal output */
+            n = -1022 - iy;
+            if(n<=20) {
+                lx = (lx>>n)|((uint32_t)hx<<(32-n));
+                hx >>= n;
+            } else if (n<=31) {
+                lx = (hx<<(32-n))|(lx>>n); hx = sx;
+            } else {
+                lx = hx>>(n-32); hx = sx;
+            }
+            INSERT_WORDS(x,hx|sx,lx);
+            x *= one;           /* create necessary signal */
+        }
+        return x;               /* exact output */
+}
diff --git a/src/math/e_fmodf.c b/src/math/e_fmodf.c
new file mode 100644 (file)
index 0000000..fe86cb0
--- /dev/null
@@ -0,0 +1,101 @@
+/* e_fmodf.c -- float version of e_fmod.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * fmodf(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one = 1.0, Zero[] = {0.0, -0.0,};
+
+float
+fmodf(float x, float y)
+{
+        int32_t n,hx,hy,hz,ix,iy,sx,i;
+
+        GET_FLOAT_WORD(hx,x);
+        GET_FLOAT_WORD(hy,y);
+        sx = hx&0x80000000;             /* sign of x */
+        hx ^=sx;                /* |x| */
+        hy &= 0x7fffffff;       /* |y| */
+
+    /* purge off exception values */
+        if(hy==0||(hx>=0x7f800000)||            /* y=0,or x not finite */
+           (hy>0x7f800000))                     /* or y is NaN */
+            return (x*y)/(x*y);
+        if(hx<hy) return x;                     /* |x|<|y| return x */
+        if(hx==hy)
+            return Zero[(uint32_t)sx>>31];     /* |x|=|y| return x*0*/
+
+    /* determine ix = ilogb(x) */
+        if(hx<0x00800000) {     /* subnormal x */
+            for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+        } else ix = (hx>>23)-127;
+
+    /* determine iy = ilogb(y) */
+        if(hy<0x00800000) {     /* subnormal y */
+            for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
+        } else iy = (hy>>23)-127;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+        if(ix >= -126)
+            hx = 0x00800000|(0x007fffff&hx);
+        else {          /* subnormal x, shift x to normal */
+            n = -126-ix;
+            hx = hx<<n;
+        }
+        if(iy >= -126)
+            hy = 0x00800000|(0x007fffff&hy);
+        else {          /* subnormal y, shift y to normal */
+            n = -126-iy;
+            hy = hy<<n;
+        }
+
+    /* fix point fmod */
+        n = ix - iy;
+        while(n--) {
+            hz=hx-hy;
+            if(hz<0){hx = hx+hx;}
+            else {
+                if(hz==0)               /* return sign(x)*0 */
+                    return Zero[(uint32_t)sx>>31];
+                hx = hz+hz;
+            }
+        }
+        hz=hx-hy;
+        if(hz>=0) {hx=hz;}
+
+    /* convert back to floating value and restore the sign */
+        if(hx==0)                       /* return sign(x)*0 */
+            return Zero[(uint32_t)sx>>31];
+        while(hx<0x00800000) {          /* normalize x */
+            hx = hx+hx;
+            iy -= 1;
+        }
+        if(iy>= -126) {         /* normalize output */
+            hx = ((hx-0x00800000)|((iy+127)<<23));
+            SET_FLOAT_WORD(x,hx|sx);
+        } else {                /* subnormal output */
+            n = -126 - iy;
+            hx >>= n;
+            SET_FLOAT_WORD(x,hx|sx);
+            x *= one;           /* create necessary signal */
+        }
+        return x;               /* exact output */
+}
diff --git a/src/math/e_hypot.c b/src/math/e_hypot.c
new file mode 100644 (file)
index 0000000..e925adc
--- /dev/null
@@ -0,0 +1,121 @@
+
+/* @(#)e_hypot.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* hypot(x,y)
+ *
+ * Method :                  
+ *      If (assume round-to-nearest) z=x*x+y*y 
+ *      has error less than sqrt(2)/2 ulp, than 
+ *      sqrt(z) has error less than 1 ulp (exercise).
+ *
+ *      So, compute sqrt(x*x+y*y) with some care as 
+ *      follows to get the error below 1 ulp:
+ *
+ *      Assume x>y>0;
+ *      (if possible, set rounding to round-to-nearest)
+ *      1. if x > 2y  use
+ *              x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ *      where x1 = x with lower 32 bits cleared, x2 = x-x1; else
+ *      2. if x <= 2y use
+ *              t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
+ *      where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, 
+ *      y1= y with lower 32 bits chopped, y2 = y-y1.
+ *              
+ *      NOTE: scaling may be necessary if some argument is too 
+ *            large or too tiny
+ *
+ * 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 sqrt(x^2+y^2) with error less 
+ *      than 1 ulps (units in the last place) 
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+hypot(double x, double y)
+{
+        double a=x,b=y,t1,t2,y1,y2,w;
+        int32_t j,k,ha,hb;
+
+        GET_HIGH_WORD(ha,x);
+        ha &= 0x7fffffff;
+        GET_HIGH_WORD(hb,y);
+        hb &= 0x7fffffff;
+        if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+        SET_HIGH_WORD(a,ha);    /* a <- |a| */
+        SET_HIGH_WORD(b,hb);    /* b <- |b| */
+        if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
+        k=0;
+        if(ha > 0x5f300000) {   /* a>2**500 */
+           if(ha >= 0x7ff00000) {       /* Inf or NaN */
+               uint32_t low;
+               w = a+b;                 /* for sNaN */
+               GET_LOW_WORD(low,a);
+               if(((ha&0xfffff)|low)==0) w = a;
+               GET_LOW_WORD(low,b);
+               if(((hb^0x7ff00000)|low)==0) w = b;
+               return w;
+           }
+           /* scale a and b by 2**-600 */
+           ha -= 0x25800000; hb -= 0x25800000;  k += 600;
+           SET_HIGH_WORD(a,ha);
+           SET_HIGH_WORD(b,hb);
+        }
+        if(hb < 0x20b00000) {   /* b < 2**-500 */
+            if(hb <= 0x000fffff) {      /* subnormal b or 0 */
+                uint32_t low;
+                GET_LOW_WORD(low,b);
+                if((hb|low)==0) return a;
+                t1=0;
+                SET_HIGH_WORD(t1,0x7fd00000);   /* t1=2^1022 */
+                b *= t1;
+                a *= t1;
+                k -= 1022;
+            } else {            /* scale a and b by 2^600 */
+                ha += 0x25800000;       /* a *= 2^600 */
+                hb += 0x25800000;       /* b *= 2^600 */
+                k -= 600;
+                SET_HIGH_WORD(a,ha);
+                SET_HIGH_WORD(b,hb);
+            }
+        }
+    /* medium size a and b */
+        w = a-b;
+        if (w>b) {
+            t1 = 0;
+            SET_HIGH_WORD(t1,ha);
+            t2 = a-t1;
+            w  = sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
+        } else {
+            a  = a+a;
+            y1 = 0;
+            SET_HIGH_WORD(y1,hb);
+            y2 = b - y1;
+            t1 = 0;
+            SET_HIGH_WORD(t1,ha+0x00100000);
+            t2 = a - t1;
+            w  = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+        }
+        if(k!=0) {
+            uint32_t high;
+            t1 = 1.0;
+            GET_HIGH_WORD(high,t1);
+            SET_HIGH_WORD(t1,high+(k<<20));
+            return t1*w;
+        } else return w;
+}
diff --git a/src/math/e_hypotf.c b/src/math/e_hypotf.c
new file mode 100644 (file)
index 0000000..1377355
--- /dev/null
@@ -0,0 +1,79 @@
+/* e_hypotf.c -- float version of e_hypot.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+hypotf(float x, float y)
+{
+        float a=x,b=y,t1,t2,y1,y2,w;
+        int32_t j,k,ha,hb;
+
+        GET_FLOAT_WORD(ha,x);
+        ha &= 0x7fffffff;
+        GET_FLOAT_WORD(hb,y);
+        hb &= 0x7fffffff;
+        if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+        SET_FLOAT_WORD(a,ha);   /* a <- |a| */
+        SET_FLOAT_WORD(b,hb);   /* b <- |b| */
+        if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
+        k=0;
+        if(ha > 0x58800000) {   /* a>2**50 */
+           if(ha >= 0x7f800000) {       /* Inf or NaN */
+               w = a+b;                 /* for sNaN */
+               if(ha == 0x7f800000) w = a;
+               if(hb == 0x7f800000) w = b;
+               return w;
+           }
+           /* scale a and b by 2**-68 */
+           ha -= 0x22000000; hb -= 0x22000000;  k += 68;
+           SET_FLOAT_WORD(a,ha);
+           SET_FLOAT_WORD(b,hb);
+        }
+        if(hb < 0x26800000) {   /* b < 2**-50 */
+            if(hb <= 0x007fffff) {      /* subnormal b or 0 */
+                if(hb==0) return a;
+                SET_FLOAT_WORD(t1,0x7e800000);  /* t1=2^126 */
+                b *= t1;
+                a *= t1;
+                k -= 126;
+            } else {            /* scale a and b by 2^68 */
+                ha += 0x22000000;       /* a *= 2^68 */
+                hb += 0x22000000;       /* b *= 2^68 */
+                k -= 68;
+                SET_FLOAT_WORD(a,ha);
+                SET_FLOAT_WORD(b,hb);
+            }
+        }
+    /* medium size a and b */
+        w = a-b;
+        if (w>b) {
+            SET_FLOAT_WORD(t1,ha&0xfffff000);
+            t2 = a-t1;
+            w  = sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
+        } else {
+            a  = a+a;
+            SET_FLOAT_WORD(y1,hb&0xfffff000);
+            y2 = b - y1;
+            SET_FLOAT_WORD(t1,ha+0x00800000);
+            t2 = a - t1;
+            w  = sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+        }
+        if(k!=0) {
+            SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
+            return t1*w;
+        } else return w;
+}
diff --git a/src/math/e_log.c b/src/math/e_log.c
new file mode 100644 (file)
index 0000000..9eb0e44
--- /dev/null
@@ -0,0 +1,131 @@
+
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* log(x)
+ * Return the logrithm of x
+ *
+ * Method :                  
+ *   1. Argument Reduction: find k and f such that 
+ *                      x = 2^k * (1+f), 
+ *         where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *      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 + .....,
+ *               = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate 
+ *      a polynomial of degree 14 to approximate R The maximum error 
+ *      of this polynomial approximation is bounded by 2**-58.45. In
+ *      other words,
+ *                      2      4      6      8      10      12      14
+ *          R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *      (the values of Lg1 to Lg7 are listed in the program)
+ *      and
+ *          |      2          14          |     -58.45
+ *          | Lg1*s +...+Lg7*s    -  R(z) | <= 2 
+ *          |                             |
+ *      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *      In order to guarantee error in log below 1ulp, we compute log
+ *      by
+ *              log(1+f) = f - s*(f - R)        (if f is not too large)
+ *              log(1+f) = f - (hfsq - s*(hfsq+R)).     (better accuracy)
+ *      
+ *      3. Finally,  log(x) = k*ln2 + log(1+f).  
+ *                          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *         Here ln2 is split into two floating point number: 
+ *                      ln2_hi + ln2_lo,
+ *         where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *      log(x) is NaN with signal if x < 0 (including -INF) ; 
+ *      log(+INF) is +INF; log(0) is -INF with signal;
+ *      log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit 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 <math.h>
+#include "math_private.h"
+
+static const double
+ln2_hi  =  6.93147180369123816490e-01,  /* 3fe62e42 fee00000 */
+ln2_lo  =  1.90821492927058770002e-10,  /* 3dea39ef 35793c76 */
+two54   =  1.80143985094819840000e+16,  /* 43500000 00000000 */
+Lg1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
+Lg2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
+Lg3 = 2.857142874366239149e-01,  /* 3FD24924 94229359 */
+Lg4 = 2.222219843214978396e-01,  /* 3FCC71C5 1D8E78AF */
+Lg5 = 1.818357216161805012e-01,  /* 3FC74664 96CB03DE */
+Lg6 = 1.531383769920937332e-01,  /* 3FC39A09 D078C69F */
+Lg7 = 1.479819860511658591e-01;  /* 3FC2F112 DF3E5244 */
+
+static const double zero   =  0.0;
+
+double
+log(double x)
+{
+        double hfsq,f,s,z,R,w,t1,t2,dk;
+        int32_t k,hx,i,j;
+        uint32_t lx;
+
+        EXTRACT_WORDS(hx,lx,x);
+
+        k=0;
+        if (hx < 0x00100000) {                  /* x < 2**-1022  */
+            if (((hx&0x7fffffff)|lx)==0) 
+                return -two54/zero;             /* log(+-0)=-inf */
+            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
+            k -= 54; x *= two54; /* subnormal number, scale up x */
+            GET_HIGH_WORD(hx,x);
+        } 
+        if (hx >= 0x7ff00000) return x+x;
+        k += (hx>>20)-1023;
+        hx &= 0x000fffff;
+        i = (hx+0x95f64)&0x100000;
+        SET_HIGH_WORD(x,hx|(i^0x3ff00000));     /* normalize x or x/2 */
+        k += (i>>20);
+        f = x-1.0;
+        if((0x000fffff&(2+hx))<3) {     /* |f| < 2**-20 */
+            if(f==zero) { if(k==0) return zero;  else {dk=(double)k;
+                                 return dk*ln2_hi+dk*ln2_lo;} }
+            R = f*f*(0.5-0.33333333333333333*f);
+            if(k==0) return f-R; else {dk=(double)k;
+                     return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+        }
+        s = f/(2.0+f); 
+        dk = (double)k;
+        z = s*s;
+        i = hx-0x6147a;
+        w = z*z;
+        j = 0x6b851-hx;
+        t1= w*(Lg2+w*(Lg4+w*Lg6)); 
+        t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); 
+        i |= j;
+        R = t2+t1;
+        if(i>0) {
+            hfsq=0.5*f*f;
+            if(k==0) return f-(hfsq-s*(hfsq+R)); else
+                     return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+        } else {
+            if(k==0) return f-s*(f-R); else
+                     return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+        }
+}
diff --git a/src/math/e_log10.c b/src/math/e_log10.c
new file mode 100644 (file)
index 0000000..3be179f
--- /dev/null
@@ -0,0 +1,83 @@
+
+/* @(#)e_log10.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* log10(x)
+ * Return the base 10 logarithm of x
+ * 
+ * Method :
+ *      Let log10_2hi = leading 40 bits of log10(2) and
+ *          log10_2lo = log10(2) - log10_2hi,
+ *          ivln10   = 1/log(10) rounded.
+ *      Then
+ *              n = ilogb(x), 
+ *              if(n<0)  n = n+1;
+ *              x = scalbn(x,-n);
+ *              log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
+ *
+ * Note 1:
+ *      To guarantee log10(10**n)=n, where 10**n is normal, the rounding 
+ *      mode must set to Round-to-Nearest.
+ * Note 2:
+ *      [1/log(10)] rounded to 53 bits has error  .198   ulps;
+ *      log10 is monotonic at all binary break points.
+ *
+ * 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;
+ *      log10(10**N) = N  for N=0,1,...,22.
+ *
+ * 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 <math.h>
+#include "math_private.h"
+
+static const double
+two54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+ivln10     =  4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
+log10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
+log10_2lo  =  3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
+
+static const double zero   =  0.0;
+
+double
+log10(double x)
+{
+        double y,z;
+        int32_t i,k,hx;
+        uint32_t lx;
+
+        EXTRACT_WORDS(hx,lx,x);
+
+        k=0;
+        if (hx < 0x00100000) {                  /* x < 2**-1022  */
+            if (((hx&0x7fffffff)|lx)==0)
+                return -two54/zero;             /* log(+-0)=-inf */
+            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
+            k -= 54; x *= two54; /* subnormal number, scale up x */
+            GET_HIGH_WORD(hx,x);
+        }
+        if (hx >= 0x7ff00000) return x+x;
+        k += (hx>>20)-1023;
+        i  = ((uint32_t)k&0x80000000)>>31;
+        hx = (hx&0x000fffff)|((0x3ff-i)<<20);
+        y  = (double)(k+i);
+        SET_HIGH_WORD(x,hx);
+        z  = y*log10_2lo + ivln10*log(x);
+        return  z+y*log10_2hi;
+}
diff --git a/src/math/e_log10f.c b/src/math/e_log10f.c
new file mode 100644 (file)
index 0000000..8fc5c5c
--- /dev/null
@@ -0,0 +1,51 @@
+/* e_log10f.c -- float version of e_log10.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+two25      =  3.3554432000e+07, /* 0x4c000000 */
+ivln10     =  4.3429449201e-01, /* 0x3ede5bd9 */
+log10_2hi  =  3.0102920532e-01, /* 0x3e9a2080 */
+log10_2lo  =  7.9034151668e-07; /* 0x355427db */
+
+static const float zero   =  0.0;
+
+float
+log10f(float x)
+{
+        float y,z;
+        int32_t i,k,hx;
+
+        GET_FLOAT_WORD(hx,x);
+
+        k=0;
+        if (hx < 0x00800000) {                  /* x < 2**-126  */
+            if ((hx&0x7fffffff)==0)
+                return -two25/zero;             /* log(+-0)=-inf */
+            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
+            k -= 25; x *= two25; /* subnormal number, scale up x */
+            GET_FLOAT_WORD(hx,x);
+        }
+        if (hx >= 0x7f800000) return x+x;
+        k += (hx>>23)-127;
+        i  = ((uint32_t)k&0x80000000)>>31;
+        hx = (hx&0x007fffff)|((0x7f-i)<<23);
+        y  = (float)(k+i);
+        SET_FLOAT_WORD(x,hx);
+        z  = y*log10_2lo + ivln10*logf(x);
+        return  z+y*log10_2hi;
+}
diff --git a/src/math/e_logf.c b/src/math/e_logf.c
new file mode 100644 (file)
index 0000000..46a8b8c
--- /dev/null
@@ -0,0 +1,81 @@
+/* e_logf.c -- float version of e_log.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+ln2_hi =   6.9313812256e-01,    /* 0x3f317180 */
+ln2_lo =   9.0580006145e-06,    /* 0x3717f7d1 */
+two25 =    3.355443200e+07,     /* 0x4c000000 */
+Lg1 = 6.6666668653e-01, /* 3F2AAAAB */
+Lg2 = 4.0000000596e-01, /* 3ECCCCCD */
+Lg3 = 2.8571429849e-01, /* 3E924925 */
+Lg4 = 2.2222198546e-01, /* 3E638E29 */
+Lg5 = 1.8183572590e-01, /* 3E3A3325 */
+Lg6 = 1.5313838422e-01, /* 3E1CD04F */
+Lg7 = 1.4798198640e-01; /* 3E178897 */
+
+static const float zero   =  0.0;
+
+float
+logf(float x)
+{
+        float hfsq,f,s,z,R,w,t1,t2,dk;
+        int32_t k,ix,i,j;
+
+        GET_FLOAT_WORD(ix,x);
+
+        k=0;
+        if (ix < 0x00800000) {                  /* x < 2**-126  */
+            if ((ix&0x7fffffff)==0)
+                return -two25/zero;             /* log(+-0)=-inf */
+            if (ix<0) return (x-x)/zero;        /* log(-#) = NaN */
+            k -= 25; x *= two25; /* subnormal number, scale up x */
+            GET_FLOAT_WORD(ix,x);
+        }
+        if (ix >= 0x7f800000) return x+x;
+        k += (ix>>23)-127;
+        ix &= 0x007fffff;
+        i = (ix+(0x95f64<<3))&0x800000;
+        SET_FLOAT_WORD(x,ix|(i^0x3f800000));    /* normalize x or x/2 */
+        k += (i>>23);
+        f = x-(float)1.0;
+        if((0x007fffff&(15+ix))<16) {   /* |f| < 2**-20 */
+            if(f==zero) { if(k==0) return zero;  else {dk=(float)k;
+                                 return dk*ln2_hi+dk*ln2_lo;} }
+            R = f*f*((float)0.5-(float)0.33333333333333333*f);
+            if(k==0) return f-R; else {dk=(float)k;
+                     return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+        }
+        s = f/((float)2.0+f);
+        dk = (float)k;
+        z = s*s;
+        i = ix-(0x6147a<<3);
+        w = z*z;
+        j = (0x6b851<<3)-ix;
+        t1= w*(Lg2+w*(Lg4+w*Lg6));
+        t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+        i |= j;
+        R = t2+t1;
+        if(i>0) {
+            hfsq=(float)0.5*f*f;
+            if(k==0) return f-(hfsq-s*(hfsq+R)); else
+                     return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+        } else {
+            if(k==0) return f-s*(f-R); else
+                     return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+        }
+}
diff --git a/src/math/e_pow.c b/src/math/e_pow.c
new file mode 100644 (file)
index 0000000..aad2428
--- /dev/null
@@ -0,0 +1,300 @@
+/* @(#)e_pow.c 1.5 04/04/22 SMI */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* pow(x,y) return x**y
+ *
+ *                    n
+ * Method:  Let x =  2   * (1+f)
+ *      1. Compute and return log2(x) in two pieces:
+ *              log2(x) = w1 + w2,
+ *         where w1 has 53-24 = 29 bit trailing zeros.
+ *      2. Perform y*log2(x) = n+y' by simulating muti-precision 
+ *         arithmetic, where |y'|<=0.5.
+ *      3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ *      1.  (anything) ** 0  is 1
+ *      2.  (anything) ** 1  is itself
+ *      3.  (anything) ** NAN is NAN
+ *      4.  NAN ** (anything except 0) is NAN
+ *      5.  +-(|x| > 1) **  +INF is +INF
+ *      6.  +-(|x| > 1) **  -INF is +0
+ *      7.  +-(|x| < 1) **  +INF is +0
+ *      8.  +-(|x| < 1) **  -INF is +INF
+ *      9.  +-1         ** +-INF is NAN
+ *      10. +0 ** (+anything except 0, NAN)               is +0
+ *      11. -0 ** (+anything except 0, NAN, odd integer)  is +0
+ *      12. +0 ** (-anything except 0, NAN)               is +INF
+ *      13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
+ *      14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ *      15. +INF ** (+anything except 0,NAN) is +INF
+ *      16. +INF ** (-anything except 0,NAN) is +0
+ *      17. -INF ** (anything)  = -0 ** (-anything)
+ *      18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ *      19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ *      pow(x,y) returns x**y nearly rounded. In particular
+ *                      pow(integer,integer)
+ *      always returns the correct integer provided it is 
+ *      representable.
+ *
+ * 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 <math.h>
+#include "math_private.h"
+
+static const double
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero    =  0.0,
+one     =  1.0,
+two     =  2.0,
+two53   =  9007199254740992.0,  /* 0x43400000, 0x00000000 */
+huge    =  1.0e300,
+tiny    =  1.0e-300,
+        /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1  =  5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2  =  4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3  =  3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4  =  2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5  =  2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6  =  2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5   =  4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2  =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h  =  6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l  = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt =  8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp    =  9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h  =  9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l  = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2    =  1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h  =  1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l  =  1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+double
+pow(double x, double y)
+{
+        double z,ax,z_h,z_l,p_h,p_l;
+        double y1,t1,t2,r,s,t,u,v,w;
+        int32_t i,j,k,yisint,n;
+        int32_t hx,hy,ix,iy;
+        uint32_t lx,ly;
+
+        EXTRACT_WORDS(hx,lx,x);
+        EXTRACT_WORDS(hy,ly,y);
+        ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+        if((iy|ly)==0) return one;      
+
+    /* +-NaN return x+y */
+        if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+           iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) 
+                return x+y;     
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0       ... y is not an integer
+     * yisint = 1       ... y is an odd int
+     * yisint = 2       ... y is an even int
+     */
+        yisint  = 0;
+        if(hx<0) {      
+            if(iy>=0x43400000) yisint = 2; /* even integer y */
+            else if(iy>=0x3ff00000) {
+                k = (iy>>20)-0x3ff;        /* exponent */
+                if(k>20) {
+                    j = ly>>(52-k);
+                    if((j<<(52-k))==ly) yisint = 2-(j&1);
+                } else if(ly==0) {
+                    j = iy>>(20-k);
+                    if((j<<(20-k))==iy) yisint = 2-(j&1);
+                }
+            }           
+        } 
+
+    /* special value of y */
+        if(ly==0) {     
+            if (iy==0x7ff00000) {       /* y is +-inf */
+                if(((ix-0x3ff00000)|lx)==0)
+                    return  y - y;      /* inf**+-1 is NaN */
+                else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+                    return (hy>=0)? y: zero;
+                else                    /* (|x|<1)**-,+inf = inf,0 */
+                    return (hy<0)?-y: zero;
+            } 
+            if(iy==0x3ff00000) {        /* y is  +-1 */
+                if(hy<0) return one/x; else return x;
+            }
+            if(hy==0x40000000) return x*x; /* y is  2 */
+            if(hy==0x3fe00000) {        /* y is  0.5 */
+                if(hx>=0)       /* x >= +0 */
+                return sqrt(x); 
+            }
+        }
+
+        ax   = fabs(x);
+    /* special value of x */
+        if(lx==0) {
+            if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+                z = ax;                 /*x is +-0,+-inf,+-1*/
+                if(hy<0) z = one/z;     /* z = (1/|x|) */
+                if(hx<0) {
+                    if(((ix-0x3ff00000)|yisint)==0) {
+                        z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+                    } else if(yisint==1) 
+                        z = -z;         /* (x<0)**odd = -(|x|**odd) */
+                }
+                return z;
+            }
+        }
+    
+    /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be
+        n = (hx>>31)+1;
+       but ANSI C says a right shift of a signed negative quantity is
+       implementation defined.  */
+        n = ((uint32_t)hx>>31)-1;
+
+    /* (x<0)**(non-int) is NaN */
+        if((n|yisint)==0) return (x-x)/(x-x);
+
+        s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+        if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
+
+    /* |y| is huge */
+        if(iy>0x41e00000) { /* if |y| > 2**31 */
+            if(iy>0x43f00000){  /* if |y| > 2**64, must o/uflow */
+                if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+                if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+            }
+        /* over/underflow if x is not close to one */
+            if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
+            if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
+        /* now |1-x| is tiny <= 2**-20, suffice to compute 
+           log(x) by x-x^2/2+x^3/3-x^4/4 */
+            t = ax-one;         /* t has 20 trailing zeros */
+            w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+            u = ivln2_h*t;      /* ivln2_h has 21 sig. bits */
+            v = t*ivln2_l-w*ivln2;
+            t1 = u+v;
+            SET_LOW_WORD(t1,0);
+            t2 = v-(t1-u);
+        } else {
+            double ss,s2,s_h,s_l,t_h,t_l;
+            n = 0;
+        /* take care subnormal number */
+            if(ix<0x00100000)
+                {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
+            n  += ((ix)>>20)-0x3ff;
+            j  = ix&0x000fffff;
+        /* determine interval */
+            ix = j|0x3ff00000;          /* normalize ix */
+            if(j<=0x3988E) k=0;         /* |x|<sqrt(3/2) */
+            else if(j<0xBB67A) k=1;     /* |x|<sqrt(3)   */
+            else {k=0;n+=1;ix -= 0x00100000;}
+            SET_HIGH_WORD(ax,ix);
+
+        /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+            u = ax-bp[k];               /* bp[0]=1.0, bp[1]=1.5 */
+            v = one/(ax+bp[k]);
+            ss = u*v;
+            s_h = ss;
+            SET_LOW_WORD(s_h,0);
+        /* t_h=ax+bp[k] High */
+            t_h = zero;
+            SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
+            t_l = ax - (t_h-bp[k]);
+            s_l = v*((u-s_h*t_h)-s_h*t_l);
+        /* compute log(ax) */
+            s2 = ss*ss;
+            r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+            r += s_l*(s_h+ss);
+            s2  = s_h*s_h;
+            t_h = 3.0+s2+r;
+            SET_LOW_WORD(t_h,0);
+            t_l = r-((t_h-3.0)-s2);
+        /* u+v = ss*(1+...) */
+            u = s_h*t_h;
+            v = s_l*t_h+t_l*ss;
+        /* 2/(3log2)*(ss+...) */
+            p_h = u+v;
+            SET_LOW_WORD(p_h,0);
+            p_l = v-(p_h-u);
+            z_h = cp_h*p_h;             /* cp_h+cp_l = 2/(3*log2) */
+            z_l = cp_l*p_h+p_l*cp+dp_l[k];
+        /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+            t = (double)n;
+            t1 = (((z_h+z_l)+dp_h[k])+t);
+            SET_LOW_WORD(t1,0);
+            t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+        }
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+        y1  = y;
+        SET_LOW_WORD(y1,0);
+        p_l = (y-y1)*t1+y*t2;
+        p_h = y1*t1;
+        z = p_l+p_h;
+        EXTRACT_WORDS(j,i,z);
+        if (j>=0x40900000) {                            /* z >= 1024 */
+            if(((j-0x40900000)|i)!=0)                   /* if z > 1024 */
+                return s*huge*huge;                     /* overflow */
+            else {
+                if(p_l+ovt>z-p_h) return s*huge*huge;   /* overflow */
+            }
+        } else if((j&0x7fffffff)>=0x4090cc00 ) {        /* z <= -1075 */
+            if(((j-0xc090cc00)|i)!=0)           /* z < -1075 */
+                return s*tiny*tiny;             /* underflow */
+            else {
+                if(p_l<=z-p_h) return s*tiny*tiny;      /* underflow */
+            }
+        }
+    /*
+     * compute 2**(p_h+p_l)
+     */
+        i = j&0x7fffffff;
+        k = (i>>20)-0x3ff;
+        n = 0;
+        if(i>0x3fe00000) {              /* if |z| > 0.5, set n = [z+0.5] */
+            n = j+(0x00100000>>(k+1));
+            k = ((n&0x7fffffff)>>20)-0x3ff;     /* new k for n */
+            t = zero;
+            SET_HIGH_WORD(t,n&~(0x000fffff>>k));
+            n = ((n&0x000fffff)|0x00100000)>>(20-k);
+            if(j<0) n = -n;
+            p_h -= t;
+        } 
+        t = p_l+p_h;
+        SET_LOW_WORD(t,0);
+        u = t*lg2_h;
+        v = (p_l-(t-p_h))*lg2+t*lg2_l;
+        z = u+v;
+        w = v-(z-u);
+        t  = z*z;
+        t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+        r  = (z*t1)/(t1-two)-(w+z*w);
+        z  = one-(r-z);
+        GET_HIGH_WORD(j,z);
+        j += (n<<20);
+        if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */
+        else SET_HIGH_WORD(z,j);
+        return s*z;
+}
diff --git a/src/math/e_powf.c b/src/math/e_powf.c
new file mode 100644 (file)
index 0000000..ae61c24
--- /dev/null
@@ -0,0 +1,243 @@
+/* e_powf.c -- float version of e_pow.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
+dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
+zero    =  0.0,
+one     =  1.0,
+two     =  2.0,
+two24   =  16777216.0,  /* 0x4b800000 */
+huge    =  1.0e30,
+tiny    =  1.0e-30,
+        /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1  =  6.0000002384e-01, /* 0x3f19999a */
+L2  =  4.2857143283e-01, /* 0x3edb6db7 */
+L3  =  3.3333334327e-01, /* 0x3eaaaaab */
+L4  =  2.7272811532e-01, /* 0x3e8ba305 */
+L5  =  2.3066075146e-01, /* 0x3e6c3255 */
+L6  =  2.0697501302e-01, /* 0x3e53f142 */
+P1   =  1.6666667163e-01, /* 0x3e2aaaab */
+P2   = -2.7777778450e-03, /* 0xbb360b61 */
+P3   =  6.6137559770e-05, /* 0x388ab355 */
+P4   = -1.6533901999e-06, /* 0xb5ddea0e */
+P5   =  4.1381369442e-08, /* 0x3331bb4c */
+lg2  =  6.9314718246e-01, /* 0x3f317218 */
+lg2_h  =  6.93145752e-01, /* 0x3f317200 */
+lg2_l  =  1.42860654e-06, /* 0x35bfbe8c */
+ovt =  4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
+cp    =  9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
+cp_h  =  9.6179199219e-01, /* 0x3f763800 =head of cp */
+cp_l  =  4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */
+ivln2    =  1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
+ivln2_h  =  1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
+ivln2_l  =  7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
+
+float
+powf(float x, float y)
+{
+        float z,ax,z_h,z_l,p_h,p_l;
+        float y1,t1,t2,r,s,sn,t,u,v,w;
+        int32_t i,j,k,yisint,n;
+        int32_t hx,hy,ix,iy,is;
+
+        GET_FLOAT_WORD(hx,x);
+        GET_FLOAT_WORD(hy,y);
+        ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+        if(iy==0) return one;
+
+    /* +-NaN return x+y */
+        if(ix > 0x7f800000 ||
+           iy > 0x7f800000)
+                return x+y;
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0       ... y is not an integer
+     * yisint = 1       ... y is an odd int
+     * yisint = 2       ... y is an even int
+     */
+        yisint  = 0;
+        if(hx<0) {
+            if(iy>=0x4b800000) yisint = 2; /* even integer y */
+            else if(iy>=0x3f800000) {
+                k = (iy>>23)-0x7f;         /* exponent */
+                j = iy>>(23-k);
+                if((j<<(23-k))==iy) yisint = 2-(j&1);
+            }
+        }
+
+    /* special value of y */
+        if (iy==0x7f800000) {   /* y is +-inf */
+            if (ix==0x3f800000)
+                return  y - y;  /* inf**+-1 is NaN */
+            else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */
+                return (hy>=0)? y: zero;
+            else                        /* (|x|<1)**-,+inf = inf,0 */
+                return (hy<0)?-y: zero;
+        }
+        if(iy==0x3f800000) {    /* y is  +-1 */
+            if(hy<0) return one/x; else return x;
+        }
+        if(hy==0x40000000) return x*x; /* y is  2 */
+        if(hy==0x3f000000) {    /* y is  0.5 */
+            if(hx>=0)   /* x >= +0 */
+            return sqrtf(x);
+        }
+
+        ax   = fabsf(x);
+    /* special value of x */
+        if(ix==0x7f800000||ix==0||ix==0x3f800000){
+            z = ax;                     /*x is +-0,+-inf,+-1*/
+            if(hy<0) z = one/z; /* z = (1/|x|) */
+            if(hx<0) {
+                if(((ix-0x3f800000)|yisint)==0) {
+                    z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+                } else if(yisint==1)
+                    z = -z;             /* (x<0)**odd = -(|x|**odd) */
+            }
+            return z;
+        }
+
+        n = ((uint32_t)hx>>31)-1;
+
+    /* (x<0)**(non-int) is NaN */
+        if((n|yisint)==0) return (x-x)/(x-x);
+
+        sn = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+        if((n|(yisint-1))==0) sn = -one;/* (-ve)**(odd int) */
+
+    /* |y| is huge */
+        if(iy>0x4d000000) { /* if |y| > 2**27 */
+        /* over/underflow if x is not close to one */
+            if(ix<0x3f7ffff8) return (hy<0)? sn*huge*huge:sn*tiny*tiny;
+            if(ix>0x3f800007) return (hy>0)? sn*huge*huge:sn*tiny*tiny;
+        /* now |1-x| is tiny <= 2**-20, suffice to compute
+           log(x) by x-x^2/2+x^3/3-x^4/4 */
+            t = ax-1;           /* t has 20 trailing zeros */
+            w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
+            u = ivln2_h*t;      /* ivln2_h has 16 sig. bits */
+            v = t*ivln2_l-w*ivln2;
+            t1 = u+v;
+            GET_FLOAT_WORD(is,t1);
+            SET_FLOAT_WORD(t1,is&0xfffff000);
+            t2 = v-(t1-u);
+        } else {
+            float s2,s_h,s_l,t_h,t_l;
+            n = 0;
+        /* take care subnormal number */
+            if(ix<0x00800000)
+                {ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); }
+            n  += ((ix)>>23)-0x7f;
+            j  = ix&0x007fffff;
+        /* determine interval */
+            ix = j|0x3f800000;          /* normalize ix */
+            if(j<=0x1cc471) k=0;        /* |x|<sqrt(3/2) */
+            else if(j<0x5db3d7) k=1;    /* |x|<sqrt(3)   */
+            else {k=0;n+=1;ix -= 0x00800000;}
+            SET_FLOAT_WORD(ax,ix);
+
+        /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+            u = ax-bp[k];               /* bp[0]=1.0, bp[1]=1.5 */
+            v = one/(ax+bp[k]);
+            s = u*v;
+            s_h = s;
+            GET_FLOAT_WORD(is,s_h);
+            SET_FLOAT_WORD(s_h,is&0xfffff000);
+        /* t_h=ax+bp[k] High */
+            is = ((ix>>1)&0xfffff000)|0x20000000;
+            SET_FLOAT_WORD(t_h,is+0x00400000+(k<<21));
+            t_l = ax - (t_h-bp[k]);
+            s_l = v*((u-s_h*t_h)-s_h*t_l);
+        /* compute log(ax) */
+            s2 = s*s;
+            r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+            r += s_l*(s_h+s);
+            s2  = s_h*s_h;
+            t_h = (float)3.0+s2+r;
+            GET_FLOAT_WORD(is,t_h);
+            SET_FLOAT_WORD(t_h,is&0xfffff000);
+            t_l = r-((t_h-(float)3.0)-s2);
+        /* u+v = s*(1+...) */
+            u = s_h*t_h;
+            v = s_l*t_h+t_l*s;
+        /* 2/(3log2)*(s+...) */
+            p_h = u+v;
+            GET_FLOAT_WORD(is,p_h);
+            SET_FLOAT_WORD(p_h,is&0xfffff000);
+            p_l = v-(p_h-u);
+            z_h = cp_h*p_h;             /* cp_h+cp_l = 2/(3*log2) */
+            z_l = cp_l*p_h+p_l*cp+dp_l[k];
+        /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+            t = (float)n;
+            t1 = (((z_h+z_l)+dp_h[k])+t);
+            GET_FLOAT_WORD(is,t1);
+            SET_FLOAT_WORD(t1,is&0xfffff000);
+            t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+        }
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+        GET_FLOAT_WORD(is,y);
+        SET_FLOAT_WORD(y1,is&0xfffff000);
+        p_l = (y-y1)*t1+y*t2;
+        p_h = y1*t1;
+        z = p_l+p_h;
+        GET_FLOAT_WORD(j,z);
+        if (j>0x43000000)                               /* if z > 128 */
+            return sn*huge*huge;                        /* overflow */
+        else if (j==0x43000000) {                       /* if z == 128 */
+            if(p_l+ovt>z-p_h) return sn*huge*huge;      /* overflow */
+        }
+        else if ((j&0x7fffffff)>0x43160000)             /* z <= -150 */
+            return sn*tiny*tiny;                        /* underflow */
+        else if (j==0xc3160000){                        /* z == -150 */
+            if(p_l<=z-p_h) return sn*tiny*tiny;         /* underflow */
+        }
+    /*
+     * compute 2**(p_h+p_l)
+     */
+        i = j&0x7fffffff;
+        k = (i>>23)-0x7f;
+        n = 0;
+        if(i>0x3f000000) {              /* if |z| > 0.5, set n = [z+0.5] */
+            n = j+(0x00800000>>(k+1));
+            k = ((n&0x7fffffff)>>23)-0x7f;      /* new k for n */
+            SET_FLOAT_WORD(t,n&~(0x007fffff>>k));
+            n = ((n&0x007fffff)|0x00800000)>>(23-k);
+            if(j<0) n = -n;
+            p_h -= t;
+        }
+        t = p_l+p_h;
+        GET_FLOAT_WORD(is,t);
+        SET_FLOAT_WORD(t,is&0xffff8000);
+        u = t*lg2_h;
+        v = (p_l-(t-p_h))*lg2+t*lg2_l;
+        z = u+v;
+        w = v-(z-u);
+        t  = z*z;
+        t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+        r  = (z*t1)/(t1-two)-(w+z*w);
+        z  = one-(r-z);
+        GET_FLOAT_WORD(j,z);
+        j += (n<<23);
+        if((j>>23)<=0) z = scalbnf(z,n);        /* subnormal output */
+        else SET_FLOAT_WORD(z,j);
+        return sn*z;
+}
diff --git a/src/math/e_rem_pio2.c b/src/math/e_rem_pio2.c
new file mode 100644 (file)
index 0000000..9eee36a
--- /dev/null
@@ -0,0 +1,163 @@
+
+/* @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/* __ieee754_rem_pio2(x,y)
+ * 
+ * return the remainder of x rem pi/2 in y[0]+y[1] 
+ * use __kernel_rem_pio2()
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi 
+ */
+static const int32_t two_over_pi[] = {
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, 
+};
+
+static const int32_t npio2_hw[] = {
+0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+0x404858EB, 0x404921FB,
+};
+
+/*
+ * invpio2:  53 bits of 2/pi
+ * pio2_1:   first  33 bit of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 33 bit of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  33 bit of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
+pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
+pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
+pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+int32_t __ieee754_rem_pio2(double x, double *y)
+{
+        double z,w,t,r,fn;
+        double tx[3];
+        int32_t e0,i,j,nx,n,ix,hx;
+        uint32_t low;
+
+        GET_HIGH_WORD(hx,x);            /* high word of x */
+        ix = hx&0x7fffffff;
+        if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
+            {y[0] = x; y[1] = 0; return 0;}
+        if(ix<0x4002d97c) {  /* |x| < 3pi/4, special case with n=+-1 */
+            if(hx>0) { 
+                z = x - pio2_1;
+                if(ix!=0x3ff921fb) {    /* 33+53 bit pi is good enough */
+                    y[0] = z - pio2_1t;
+                    y[1] = (z-y[0])-pio2_1t;
+                } else {                /* near pi/2, use 33+33+53 bit pi */
+                    z -= pio2_2;
+                    y[0] = z - pio2_2t;
+                    y[1] = (z-y[0])-pio2_2t;
+                }
+                return 1;
+            } else {    /* negative x */
+                z = x + pio2_1;
+                if(ix!=0x3ff921fb) {    /* 33+53 bit pi is good enough */
+                    y[0] = z + pio2_1t;
+                    y[1] = (z-y[0])+pio2_1t;
+                } else {                /* near pi/2, use 33+33+53 bit pi */
+                    z += pio2_2;
+                    y[0] = z + pio2_2t;
+                    y[1] = (z-y[0])+pio2_2t;
+                }
+                return -1;
+            }
+        }
+        if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+            t  = fabs(x);
+            n  = (int32_t) (t*invpio2+half);
+            fn = (double)n;
+            r  = t-fn*pio2_1;
+            w  = fn*pio2_1t;    /* 1st round good to 85 bit */
+            if(n<32&&ix!=npio2_hw[n-1]) {       
+                y[0] = r-w;     /* quick check no cancellation */
+            } else {
+                uint32_t high;
+                j  = ix>>20;
+                y[0] = r-w; 
+                GET_HIGH_WORD(high,y[0]);
+                i = j-((high>>20)&0x7ff);
+                if(i>16) {  /* 2nd iteration needed, good to 118 */
+                    t  = r;
+                    w  = fn*pio2_2;     
+                    r  = t-w;
+                    w  = fn*pio2_2t-((t-r)-w);  
+                    y[0] = r-w;
+                    GET_HIGH_WORD(high,y[0]);
+                    i = j-((high>>20)&0x7ff);
+                    if(i>49)  { /* 3rd iteration need, 151 bits acc */
+                        t  = r; /* will cover all possible cases */
+                        w  = fn*pio2_3; 
+                        r  = t-w;
+                        w  = fn*pio2_3t-((t-r)-w);      
+                        y[0] = r-w;
+                    }
+                }
+            }
+            y[1] = (r-y[0])-w;
+            if(hx<0)    {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+            else         return n;
+        }
+    /* 
+     * all other (large) arguments
+     */
+        if(ix>=0x7ff00000) {            /* x is inf or NaN */
+            y[0]=y[1]=x-x; return 0;
+        }
+    /* set z = scalbn(|x|,ilogb(x)-23) */
+        GET_LOW_WORD(low,x);
+        e0      = (ix>>20)-1046;        /* e0 = ilogb(z)-23; */
+       INSERT_WORDS(z, ix - ((int32_t)(e0<<20)), low);
+        for(i=0;i<2;i++) {
+                tx[i] = (double)((int32_t)(z));
+                z     = (z-tx[i])*two24;
+        }
+        tx[2] = z;
+        nx = 3;
+        while(tx[nx-1]==zero) nx--;     /* skip zero term */
+        n  =  __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
+        if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+        return n;
+}
diff --git a/src/math/e_rem_pio2f.c b/src/math/e_rem_pio2f.c
new file mode 100644 (file)
index 0000000..4992ea0
--- /dev/null
@@ -0,0 +1,175 @@
+/* e_rem_pio2f.c -- float version of e_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_rem_pio2f(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2f()
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+static const int32_t two_over_pi[] = {
+0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
+0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
+0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
+0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
+0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
+0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
+0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
+0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
+0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
+0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
+0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
+0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
+0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
+0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
+0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
+0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
+0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
+0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
+0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
+0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
+0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
+0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
+};
+
+/* This array is like the one in e_rem_pio2.c, but the numbers are
+   single precision and the last 8 bits are forced to 0.  */
+static const int32_t npio2_hw[] = {
+0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
+0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
+0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
+0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
+0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
+0x4242c700, 0x42490f00
+};
+
+/*
+ * invpio2:  24 bits of 2/pi
+ * pio2_1:   first  17 bit of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 17 bit of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  17 bit of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const float
+zero =  0.0000000000e+00, /* 0x00000000 */
+half =  5.0000000000e-01, /* 0x3f000000 */
+two8 =  2.5600000000e+02, /* 0x43800000 */
+invpio2 =  6.3661980629e-01, /* 0x3f22f984 */
+pio2_1  =  1.5707855225e+00, /* 0x3fc90f80 */
+pio2_1t =  1.0804334124e-05, /* 0x37354443 */
+pio2_2  =  1.0804273188e-05, /* 0x37354400 */
+pio2_2t =  6.0770999344e-11, /* 0x2e85a308 */
+pio2_3  =  6.0770943833e-11, /* 0x2e85a300 */
+pio2_3t =  6.1232342629e-17; /* 0x248d3132 */
+
+int32_t __ieee754_rem_pio2f(float x, float *y)
+{
+        float z,w,t,r,fn;
+        float tx[3];
+        int32_t e0,i,j,nx,n,ix,hx;
+
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix<=0x3f490fd8)   /* |x| ~<= pi/4 , no need for reduction */
+            {y[0] = x; y[1] = 0; return 0;}
+        if(ix<0x4016cbe4) {  /* |x| < 3pi/4, special case with n=+-1 */
+            if(hx>0) {
+                z = x - pio2_1;
+                if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+                    y[0] = z - pio2_1t;
+                    y[1] = (z-y[0])-pio2_1t;
+                } else {                /* near pi/2, use 24+24+24 bit pi */
+                    z -= pio2_2;
+                    y[0] = z - pio2_2t;
+                    y[1] = (z-y[0])-pio2_2t;
+                }
+                return 1;
+            } else {    /* negative x */
+                z = x + pio2_1;
+                if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
+                    y[0] = z + pio2_1t;
+                    y[1] = (z-y[0])+pio2_1t;
+                } else {                /* near pi/2, use 24+24+24 bit pi */
+                    z += pio2_2;
+                    y[0] = z + pio2_2t;
+                    y[1] = (z-y[0])+pio2_2t;
+                }
+                return -1;
+            }
+        }
+        if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
+            t  = fabsf(x);
+            n  = (int32_t) (t*invpio2+half);
+            fn = (float)n;
+            r  = t-fn*pio2_1;
+            w  = fn*pio2_1t;    /* 1st round good to 40 bit */
+            if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
+                y[0] = r-w;     /* quick check no cancellation */
+            } else {
+                uint32_t high;
+                j  = ix>>23;
+                y[0] = r-w;
+                GET_FLOAT_WORD(high,y[0]);
+                i = j-((high>>23)&0xff);
+                if(i>8) {  /* 2nd iteration needed, good to 57 */
+                    t  = r;
+                    w  = fn*pio2_2;
+                    r  = t-w;
+                    w  = fn*pio2_2t-((t-r)-w);
+                    y[0] = r-w;
+                    GET_FLOAT_WORD(high,y[0]);
+                    i = j-((high>>23)&0xff);
+                    if(i>25)  { /* 3rd iteration need, 74 bits acc */
+                        t  = r; /* will cover all possible cases */
+                        w  = fn*pio2_3;
+                        r  = t-w;
+                        w  = fn*pio2_3t-((t-r)-w);
+                        y[0] = r-w;
+                    }
+                }
+            }
+            y[1] = (r-y[0])-w;
+            if(hx<0)    {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+            else         return n;
+        }
+    /*
+     * all other (large) arguments
+     */
+        if(ix>=0x7f800000) {            /* x is inf or NaN */
+            y[0]=y[1]=x-x; return 0;
+        }
+    /* set z = scalbn(|x|,ilogb(x)-7) */
+        e0      = (ix>>23)-134;         /* e0 = ilogb(z)-7; */
+        SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
+        for(i=0;i<2;i++) {
+                tx[i] = (float)((int32_t)(z));
+                z     = (z-tx[i])*two8;
+        }
+        tx[2] = z;
+        nx = 3;
+        while(tx[nx-1]==zero) nx--;     /* skip zero term */
+        n  =  __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
+        if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+        return n;
+}
diff --git a/src/math/e_remainder.c b/src/math/e_remainder.c
new file mode 100644 (file)
index 0000000..9cb5691
--- /dev/null
@@ -0,0 +1,69 @@
+
+/* @(#)e_remainder.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* remainder(x,p)
+ * Return :                  
+ *      returns  x REM p  =  x - [x/p]*p as if in infinite 
+ *      precise arithmetic, where [x/p] is the (infinite bit) 
+ *      integer nearest x/p (in half way case choose the even one).
+ * Method : 
+ *      Based on fmod() return x-[x/p]chopped*p exactlp.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double zero = 0.0;
+
+
+double
+remainder(double x, double p)
+{
+        int32_t hx,hp;
+        uint32_t sx,lx,lp;
+        double p_half;
+
+        EXTRACT_WORDS(hx,lx,x);
+        EXTRACT_WORDS(hp,lp,p);
+        sx = hx&0x80000000;
+        hp &= 0x7fffffff;
+        hx &= 0x7fffffff;
+
+    /* purge off exception values */
+        if((hp|lp)==0) return (x*p)/(x*p);      /* p = 0 */
+        if((hx>=0x7ff00000)||                   /* x not finite */
+          ((hp>=0x7ff00000)&&                   /* p is NaN */
+          (((hp-0x7ff00000)|lp)!=0)))
+            return (x*p)/(x*p);
+
+
+        if (hp<=0x7fdfffff) x = fmod(x,p+p);  /* now x < 2p */
+        if (((hx-hp)|(lx-lp))==0) return zero*x;
+        x  = fabs(x);
+        p  = fabs(p);
+        if (hp<0x00200000) {
+            if(x+x>p) {
+                x-=p;
+                if(x+x>=p) x -= p;
+            }
+        } else {
+            p_half = 0.5*p;
+            if(x>p_half) {
+                x-=p;
+                if(x>=p_half) x -= p;
+            }
+        }
+        GET_HIGH_WORD(hx,x);
+        SET_HIGH_WORD(x,hx^sx);
+        return x;
+}
diff --git a/src/math/e_remainderf.c b/src/math/e_remainderf.c
new file mode 100644 (file)
index 0000000..c292367
--- /dev/null
@@ -0,0 +1,61 @@
+/* e_remainderf.c -- float version of e_remainder.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float zero = 0.0;
+
+
+float
+remainderf(float x, float p)
+{
+        int32_t hx,hp;
+        uint32_t sx;
+        float p_half;
+
+        GET_FLOAT_WORD(hx,x);
+        GET_FLOAT_WORD(hp,p);
+        sx = hx&0x80000000;
+        hp &= 0x7fffffff;
+        hx &= 0x7fffffff;
+
+    /* purge off exception values */
+        if(hp==0) return (x*p)/(x*p);           /* p = 0 */
+        if((hx>=0x7f800000)||                   /* x not finite */
+          ((hp>0x7f800000)))                    /* p is NaN */
+            return (x*p)/(x*p);
+
+
+        if (hp<=0x7effffff) x = fmodf(x,p+p); /* now x < 2p */
+        if ((hx-hp)==0) return zero*x;
+        x  = fabsf(x);
+        p  = fabsf(p);
+        if (hp<0x01000000) {
+            if(x+x>p) {
+                x-=p;
+                if(x+x>=p) x -= p;
+            }
+        } else {
+            p_half = (float)0.5*p;
+            if(x>p_half) {
+                x-=p;
+                if(x>=p_half) x -= p;
+            }
+        }
+        GET_FLOAT_WORD(hx,x);
+        SET_FLOAT_WORD(x,hx^sx);
+        return x;
+}
diff --git a/src/math/e_scalb.c b/src/math/e_scalb.c
new file mode 100644 (file)
index 0000000..cee2b44
--- /dev/null
@@ -0,0 +1,35 @@
+
+/* @(#)e_scalb.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * scalb(x, fn) is provide for
+ * passing various standard test suite. One 
+ * should use scalbn() instead.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+scalb(double x, double fn)
+{
+        if (isnan(x)||isnan(fn)) return x*fn;
+        if (!isfinite(fn)) {
+            if(fn>0.0) return x*fn;
+            else       return x/(-fn);
+        }
+        if (rint(fn)!=fn) return (fn-fn)/(fn-fn);
+        if ( fn > 65000.0) return scalbn(x, 65000);
+        if (-fn > 65000.0) return scalbn(x,-65000);
+        return scalbn(x,(int)fn);
+}
diff --git a/src/math/e_scalbf.c b/src/math/e_scalbf.c
new file mode 100644 (file)
index 0000000..de7d7f6
--- /dev/null
@@ -0,0 +1,31 @@
+/* e_scalbf.c -- float version of e_scalb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+scalbf(float x, float fn)
+{
+        if (isnan(x)||isnan(fn)) return x*fn;
+        if (!isfinite(fn)) {
+            if(fn>(float)0.0) return x*fn;
+            else       return x/(-fn);
+        }
+        if (rintf(fn)!=fn) return (fn-fn)/(fn-fn);
+        if ( fn > (float)65000.0) return scalbnf(x, 65000);
+        if (-fn > (float)65000.0) return scalbnf(x,-65000);
+        return scalbnf(x,(int)fn);
+}
diff --git a/src/math/e_sinh.c b/src/math/e_sinh.c
new file mode 100644 (file)
index 0000000..3a57427
--- /dev/null
@@ -0,0 +1,75 @@
+
+/* @(#)e_sinh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* sinh(x)
+ * Method : 
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ *      1. Replace x by |x| (sinh(-x) = -sinh(x)). 
+ *      2. 
+ *                                                  E + E/(E+1)
+ *          0        <= x <= 22     :  sinh(x) := --------------, E=expm1(x)
+ *                                                      2
+ *
+ *          22       <= x <= lnovft :  sinh(x) := exp(x)/2 
+ *          lnovft   <= x <= ln2ovft:  sinh(x) := exp(x/2)/2 * exp(x/2)
+ *          ln2ovft  <  x           :  sinh(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ *      sinh(x) is |x| if x is +INF, -INF, or NaN.
+ *      only sinh(0)=0 is exact for finite x.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one = 1.0, shuge = 1.0e307;
+
+double
+sinh(double x)
+{
+        double t,w,h;
+        int32_t ix,jx;
+        uint32_t lx;
+
+    /* High word of |x|. */
+        GET_HIGH_WORD(jx,x);
+        ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+        if(ix>=0x7ff00000) return x+x;  
+
+        h = 0.5;
+        if (jx<0) h = -h;
+    /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+        if (ix < 0x40360000) {          /* |x|<22 */
+            if (ix<0x3e300000)          /* |x|<2**-28 */
+                if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+            t = expm1(fabs(x));
+            if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one));
+            return h*(t+t/(t+one));
+        }
+
+    /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+        if (ix < 0x40862E42)  return h*exp(fabs(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+        GET_LOW_WORD(lx,x);
+        if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(uint32_t)0x8fb9f87d))) {
+            w = exp(0.5*fabs(x));
+            t = h*w;
+            return t*w;
+        }
+
+    /* |x| > overflowthresold, sinh(x) overflow */
+        return x*shuge;
+}
diff --git a/src/math/e_sinhf.c b/src/math/e_sinhf.c
new file mode 100644 (file)
index 0000000..fe60608
--- /dev/null
@@ -0,0 +1,56 @@
+/* e_sinhf.c -- float version of e_sinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one = 1.0, shuge = 1.0e37;
+
+float
+sinhf(float x)
+{
+        float t,w,h;
+        int32_t ix,jx;
+
+        GET_FLOAT_WORD(jx,x);
+        ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+        if(ix>=0x7f800000) return x+x;
+
+        h = 0.5;
+        if (jx<0) h = -h;
+    /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+        if (ix < 0x41b00000) {          /* |x|<22 */
+            if (ix<0x31800000)          /* |x|<2**-28 */
+                if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+            t = expm1f(fabsf(x));
+            if(ix<0x3f800000) return h*((float)2.0*t-t*t/(t+one));
+            return h*(t+t/(t+one));
+        }
+
+    /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+        if (ix < 0x42b17180)  return h*expf(fabsf(x));
+
+    /* |x| in [log(maxdouble), overflowthresold] */
+        if (ix<=0x42b2d4fc) {
+            w = expf((float)0.5*fabsf(x));
+            t = h*w;
+            return t*w;
+        }
+
+    /* |x| > overflowthresold, sinh(x) overflow */
+        return x*shuge;
+}
diff --git a/src/math/e_sqrt.c b/src/math/e_sqrt.c
new file mode 100644 (file)
index 0000000..2bc6874
--- /dev/null
@@ -0,0 +1,442 @@
+
+/* @(#)e_sqrt.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* sqrt(x)
+ * Return correctly rounded sqrt.
+ *           ------------------------------------------
+ *           |  Use the hardware sqrt if you have one |
+ *           ------------------------------------------
+ * Method: 
+ *   Bit by bit method using integer arithmetic. (Slow, but portable) 
+ *   1. Normalization
+ *      Scale x to y in [1,4) with even powers of 2: 
+ *      find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
+ *              sqrt(x) = 2^k * sqrt(y)
+ *   2. Bit by bit computation
+ *      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
+ *           i                                                   0
+ *                                     i+1         2
+ *          s  = 2*q , and      y  =  2   * ( y - q  ).         (1)
+ *           i      i            i                 i
+ *                                                        
+ *      To compute q    from q , one checks whether 
+ *                  i+1       i                       
+ *
+ *                            -(i+1) 2
+ *                      (q + 2      ) <= y.                     (2)
+ *                        i
+ *                                                            -(i+1)
+ *      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
+ *                             i+1   i             i+1   i
+ *
+ *      With some algebric manipulation, it is not difficult to see
+ *      that (2) is equivalent to 
+ *                             -(i+1)
+ *                      s  +  2       <= y                      (3)
+ *                       i                i
+ *
+ *      The advantage of (3) is that s  and y  can be computed by 
+ *                                    i      i
+ *      the following recurrence formula:
+ *          if (3) is false
+ *
+ *          s     =  s  ,       y    = y   ;                    (4)
+ *           i+1      i          i+1    i
+ *
+ *          otherwise,
+ *                         -i                     -(i+1)
+ *          s     =  s  + 2  ,  y    = y  -  s  - 2             (5)
+ *           i+1      i          i+1    i     i
+ *                              
+ *      One may easily use induction to prove (4) and (5). 
+ *      Note. Since the left hand side of (3) contain only i+2 bits,
+ *            it does not necessary to do a full (53-bit) comparison 
+ *            in (3).
+ *   3. Final rounding
+ *      After generating the 53 bits result, we compute one more bit.
+ *      Together with the remainder, we can decide whether the
+ *      result is exact, bigger than 1/2ulp, or less than 1/2ulp
+ *      (it will never equal to 1/2ulp).
+ *      The rounding mode can be detected by checking whether
+ *      huge + tiny is equal to huge, and whether huge - tiny is
+ *      equal to huge for some floating point number "huge" and "tiny".
+ *              
+ * Special cases:
+ *      sqrt(+-0) = +-0         ... exact
+ *      sqrt(inf) = inf
+ *      sqrt(-ve) = NaN         ... with invalid signal
+ *      sqrt(NaN) = NaN         ... with invalid signal for signaling NaN
+ *
+ * Other methods : see the appended file at the end of the program below.
+ *---------------
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static  const double    one     = 1.0, tiny=1.0e-300;
+
+double
+sqrt(double x)
+{
+        double z;
+        int32_t sign = (int)0x80000000;
+        int32_t ix0,s0,q,m,t,i;
+        uint32_t r,t1,s1,ix1,q1;
+
+        EXTRACT_WORDS(ix0,ix1,x);
+
+    /* take care of Inf and NaN */
+        if((ix0&0x7ff00000)==0x7ff00000) {                      
+            return x*x+x;               /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+                                           sqrt(-inf)=sNaN */
+        } 
+    /* take care of zero */
+        if(ix0<=0) {
+            if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
+            else if(ix0<0)
+                return (x-x)/(x-x);             /* sqrt(-ve) = sNaN */
+        }
+    /* normalize x */
+        m = (ix0>>20);
+        if(m==0) {                              /* subnormal x */
+            while(ix0==0) {
+                m -= 21;
+                ix0 |= (ix1>>11); ix1 <<= 21;
+            }
+            for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
+            m -= i-1;
+            ix0 |= (ix1>>(32-i));
+            ix1 <<= i;
+        }
+        m -= 1023;      /* unbias exponent */
+        ix0 = (ix0&0x000fffff)|0x00100000;
+        if(m&1){        /* odd m, double x to make it even */
+            ix0 += ix0 + ((ix1&sign)>>31);
+            ix1 += ix1;
+        }
+        m >>= 1;        /* m = [m/2] */
+
+    /* generate sqrt(x) bit by bit */
+        ix0 += ix0 + ((ix1&sign)>>31);
+        ix1 += ix1;
+        q = q1 = s0 = s1 = 0;   /* [q,q1] = sqrt(x) */
+        r = 0x00200000;         /* r = moving bit from right to left */
+
+        while(r!=0) {
+            t = s0+r; 
+            if(t<=ix0) { 
+                s0   = t+r; 
+                ix0 -= t; 
+                q   += r; 
+            } 
+            ix0 += ix0 + ((ix1&sign)>>31);
+            ix1 += ix1;
+            r>>=1;
+        }
+
+        r = sign;
+        while(r!=0) {
+            t1 = s1+r; 
+            t  = s0;
+            if((t<ix0)||((t==ix0)&&(t1<=ix1))) { 
+                s1  = t1+r;
+                if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
+                ix0 -= t;
+                if (ix1 < t1) ix0 -= 1;
+                ix1 -= t1;
+                q1  += r;
+            }
+            ix0 += ix0 + ((ix1&sign)>>31);
+            ix1 += ix1;
+            r>>=1;
+        }
+
+    /* use floating add to find out rounding direction */
+        if((ix0|ix1)!=0) {
+            z = one-tiny; /* trigger inexact flag */
+            if (z>=one) {
+                z = one+tiny;
+                if (q1==(uint32_t)0xffffffff) { q1=0; q += 1;}
+                else if (z>one) {
+                    if (q1==(uint32_t)0xfffffffe) q+=1;
+                    q1+=2; 
+                } else
+                    q1 += (q1&1);
+            }
+        }
+        ix0 = (q>>1)+0x3fe00000;
+        ix1 =  q1>>1;
+        if ((q&1)==1) ix1 |= sign;
+        ix0 += (m <<20);
+        INSERT_WORDS(z,ix0,ix1);
+        return z;
+}
+
+/*
+Other methods  (use floating-point arithmetic)
+-------------
+(This is a copy of a drafted paper by Prof W. Kahan 
+and K.C. Ng, written in May, 1986)
+
+        Two algorithms are given here to implement sqrt(x) 
+        (IEEE double precision arithmetic) in software.
+        Both supply sqrt(x) correctly rounded. The first algorithm (in
+        Section A) uses newton iterations and involves four divisions.
+        The second one uses reciproot iterations to avoid division, but
+        requires more multiplications. Both algorithms need the ability
+        to chop results of arithmetic operations instead of round them, 
+        and the INEXACT flag to indicate when an arithmetic operation
+        is executed exactly with no roundoff error, all part of the 
+        standard (IEEE 754-1985). The ability to perform shift, add,
+        subtract and logical AND operations upon 32-bit words is needed
+        too, though not part of the standard.
+
+A.  sqrt(x) by Newton Iteration
+
+   (1)  Initial approximation
+
+        Let x0 and x1 be the leading and the trailing 32-bit words of
+        a floating point number x (in IEEE double format) respectively 
+
+            1    11                  52                           ...widths
+           ------------------------------------------------------
+        x: |s|    e     |             f                         |
+           ------------------------------------------------------
+              msb    lsb  msb                                 lsb ...order
+
+             ------------------------        ------------------------
+        x0:  |s|   e    |    f1     |    x1: |          f2           |
+             ------------------------        ------------------------
+
+        By performing shifts and subtracts on x0 and x1 (both regarded
+        as integers), we obtain an 8-bit approximation of sqrt(x) as
+        follows.
+
+                k  := (x0>>1) + 0x1ff80000;
+                y0 := k - T1[31&(k>>15)].       ... y ~ sqrt(x) to 8 bits
+        Here k is a 32-bit integer and T1[] is an integer array containing
+        correction terms. Now magically the floating value of y (y's
+        leading 32-bit word is y0, the value of its trailing word is 0)
+        approximates sqrt(x) to almost 8-bit.
+
+        Value of T1:
+        static int T1[32]= {
+        0,      1024,   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,};
+
+    (2) Iterative refinement
+
+        Apply Heron's rule three times to y, we have y approximates 
+        sqrt(x) to within 1 ulp (Unit in the Last Place):
+
+                y := (y+x/y)/2          ... almost 17 sig. bits
+                y := (y+x/y)/2          ... almost 35 sig. bits
+                y := y-(y-x/y)/2        ... within 1 ulp
+
+
+        Remark 1.
+            Another way to improve y to within 1 ulp is:
+
+                y := (y+x/y)            ... almost 17 sig. bits to 2*sqrt(x)
+                y := y - 0x00100006     ... almost 18 sig. bits to sqrt(x)
+
+                                2
+                            (x-y )*y
+                y := y + 2* ----------  ...within 1 ulp
+                               2
+                             3y  + x
+
+
+        This formula has one division fewer than the one above; however,
+        it requires more multiplications and additions. Also x must be
+        scaled in advance to avoid spurious overflow in evaluating the
+        expression 3y*y+x. Hence it is not recommended uless division
+        is slow. If division is very slow, then one should use the 
+        reciproot algorithm given in section B.
+
+    (3) Final adjustment
+
+        By twiddling y's last bit it is possible to force y to be 
+        correctly rounded according to the prevailing rounding mode
+        as follows. Let r and i be copies of the rounding mode and
+        inexact flag before entering the square root program. Also we
+        use the expression y+-ulp for the next representable floating
+        numbers (up and down) of y. Note that y+-ulp = either fixed
+        point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+        mode.
+
+                I := FALSE;     ... reset INEXACT flag I
+                R := RZ;        ... set rounding mode to round-toward-zero
+                z := x/y;       ... chopped quotient, possibly inexact
+                If(not I) then {        ... if the quotient is exact
+                    if(z=y) {
+                        I := i;  ... restore inexact flag
+                        R := r;  ... restore rounded mode
+                        return sqrt(x):=y.
+                    } else {
+                        z := z - ulp;   ... special rounding
+                    }
+                }
+                i := TRUE;              ... sqrt(x) is inexact
+                If (r=RN) then z=z+ulp  ... rounded-to-nearest
+                If (r=RP) then {        ... round-toward-+inf
+                    y = y+ulp; z=z+ulp;
+                }
+                y := y+z;               ... chopped sum
+                y0:=y0-0x00100000;      ... y := y/2 is correctly rounded.
+                I := i;                 ... restore inexact flag
+                R := r;                 ... restore rounded mode
+                return sqrt(x):=y.
+                    
+    (4) Special cases
+
+        Square root of +inf, +-0, or NaN is itself;
+        Square root of a negative number is NaN with invalid signal.
+
+
+B.  sqrt(x) by Reciproot Iteration
+
+   (1)  Initial approximation
+
+        Let x0 and x1 be the leading and the trailing 32-bit words of
+        a floating point number x (in IEEE double format) respectively
+        (see section A). By performing shifs and subtracts on x0 and y0,
+        we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
+
+            k := 0x5fe80000 - (x0>>1);
+            y0:= k - T2[63&(k>>14)].    ... y ~ 1/sqrt(x) to 7.8 bits
+
+        Here k is a 32-bit integer and T2[] is an integer array 
+        containing correction terms. Now magically the floating
+        value of y (y's leading 32-bit word is y0, the value of
+        its trailing word y1 is set to zero) approximates 1/sqrt(x)
+        to almost 7.8-bit.
+
+        Value of T2:
+        static int T2[64]= {
+        0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866,
+        0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
+        0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
+        0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
+        0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
+        0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
+        0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
+        0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,};
+
+    (2) Iterative refinement
+
+        Apply Reciproot iteration three times to y and multiply the
+        result by x to get an approximation z that matches sqrt(x)
+        to about 1 ulp. To be exact, we will have 
+                -1ulp < sqrt(x)-z<1.0625ulp.
+        
+        ... set rounding mode to Round-to-nearest
+           y := y*(1.5-0.5*x*y*y)       ... almost 15 sig. bits to 1/sqrt(x)
+           y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
+        ... special arrangement for better accuracy
+           z := x*y                     ... 29 bits to sqrt(x), with z*y<1
+           z := z + 0.5*z*(1-z*y)       ... about 1 ulp to sqrt(x)
+
+        Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
+        (a) the term z*y in the final iteration is always less than 1; 
+        (b) the error in the final result is biased upward so that
+                -1 ulp < sqrt(x) - z < 1.0625 ulp
+            instead of |sqrt(x)-z|<1.03125ulp.
+
+    (3) Final adjustment
+
+        By twiddling y's last bit it is possible to force y to be 
+        correctly rounded according to the prevailing rounding mode
+        as follows. Let r and i be copies of the rounding mode and
+        inexact flag before entering the square root program. Also we
+        use the expression y+-ulp for the next representable floating
+        numbers (up and down) of y. Note that y+-ulp = either fixed
+        point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+        mode.
+
+        R := RZ;                ... set rounding mode to round-toward-zero
+        switch(r) {
+            case RN:            ... round-to-nearest
+               if(x<= z*(z-ulp)...chopped) z = z - ulp; else
+               if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
+               break;
+            case RZ:case RM:    ... round-to-zero or round-to--inf
+               R:=RP;           ... reset rounding mod to round-to-+inf
+               if(x<z*z ... rounded up) z = z - ulp; else
+               if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
+               break;
+            case RP:            ... round-to-+inf
+               if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
+               if(x>z*z ...chopped) z = z+ulp;
+               break;
+        }
+
+        Remark 3. The above comparisons can be done in fixed point. For
+        example, to compare x and w=z*z chopped, it suffices to compare
+        x1 and w1 (the trailing parts of x and w), regarding them as
+        two's complement integers.
+
+        ...Is z an exact square root?
+        To determine whether z is an exact square root of x, let z1 be the
+        trailing part of z, and also let x0 and x1 be the leading and
+        trailing parts of x.
+
+        If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0
+            I := 1;             ... Raise Inexact flag: z is not exact
+        else {
+            j := 1 - [(x0>>20)&1]       ... j = logb(x) mod 2
+            k := z1 >> 26;              ... get z's 25-th and 26-th 
+                                            fraction bits
+            I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
+        }
+        R:= r           ... restore rounded mode
+        return sqrt(x):=z.
+
+        If multiplication is cheaper then the foregoing red tape, the 
+        Inexact flag can be evaluated by
+
+            I := i;
+            I := (z*z!=x) or I.
+
+        Note that z*z can overwrite I; this value must be sensed if it is 
+        True.
+
+        Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
+        zero.
+
+                    --------------------
+                z1: |        f2        | 
+                    --------------------
+                bit 31             bit 0
+
+        Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
+        or even of logb(x) have the following relations:
+
+        -------------------------------------------------
+        bit 27,26 of z1         bit 1,0 of x1   logb(x)
+        -------------------------------------------------
+        00                      00              odd and even
+        01                      01              even
+        10                      10              odd
+        10                      00              even
+        11                      01              even
+        -------------------------------------------------
+
+    (4) Special cases (see (4) of Section A).   
+ */
diff --git a/src/math/e_sqrtf.c b/src/math/e_sqrtf.c
new file mode 100644 (file)
index 0000000..03a15be
--- /dev/null
@@ -0,0 +1,85 @@
+/* e_sqrtf.c -- float version of e_sqrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static  const float     one     = 1.0, tiny=1.0e-30;
+
+float
+sqrtf(float x)
+{
+        float z;
+        int32_t sign = (int)0x80000000;
+        int32_t ix,s,q,m,t,i;
+        uint32_t r;
+
+        GET_FLOAT_WORD(ix,x);
+
+    /* take care of Inf and NaN */
+        if((ix&0x7f800000)==0x7f800000) {
+            return x*x+x;               /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+                                           sqrt(-inf)=sNaN */
+        }
+    /* take care of zero */
+        if(ix<=0) {
+            if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
+            else if(ix<0)
+                return (x-x)/(x-x);             /* sqrt(-ve) = sNaN */
+        }
+    /* normalize x */
+        m = (ix>>23);
+        if(m==0) {                              /* subnormal x */
+            for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
+            m -= i-1;
+        }
+        m -= 127;       /* unbias exponent */
+        ix = (ix&0x007fffff)|0x00800000;
+        if(m&1) /* odd m, double x to make it even */
+            ix += ix;
+        m >>= 1;        /* m = [m/2] */
+
+    /* generate sqrt(x) bit by bit */
+        ix += ix;
+        q = s = 0;              /* q = sqrt(x) */
+        r = 0x01000000;         /* r = moving bit from right to left */
+
+        while(r!=0) {
+            t = s+r;
+            if(t<=ix) {
+                s    = t+r;
+                ix  -= t;
+                q   += r;
+            }
+            ix += ix;
+            r>>=1;
+        }
+
+    /* use floating add to find out rounding direction */
+        if(ix!=0) {
+            z = one-tiny; /* trigger inexact flag */
+            if (z>=one) {
+                z = one+tiny;
+                if (z>one)
+                    q += 2;
+                else
+                    q += (q&1);
+            }
+        }
+        ix = (q>>1)+0x3f000000;
+        ix += (m <<23);
+        SET_FLOAT_WORD(z,ix);
+        return z;
+}
diff --git a/src/math/i386/e_exp.s b/src/math/i386/e_exp.s
new file mode 100644 (file)
index 0000000..d6c54a3
--- /dev/null
@@ -0,0 +1,36 @@
+.global expf
+expf:
+       mov 4(%esp),%eax
+       flds 4(%esp)
+       shr $23,%eax
+       inc %al
+       jz 1f
+       jmp 0f
+
+.global exp
+exp:
+       mov 8(%esp),%eax
+       fldl 4(%esp)
+       shl %eax
+       cmp $0xffe00000,%eax
+       jae 1f
+
+0:     fldl2e
+       fmulp
+       fst %st(1)
+       frndint
+       fst %st(2)
+       fsubrp
+       f2xm1
+       fld1
+       faddp
+       fscale
+       fstp %st(1)
+       ret
+
+1:     fsts 4(%esp)
+       cmpl $0xff800000,4(%esp)
+       jnz 1f
+       fstp %st(0)
+       fldz
+1:     ret
diff --git a/src/math/i386/e_expf.s b/src/math/i386/e_expf.s
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/src/math/i386/e_log.s b/src/math/i386/e_log.s
new file mode 100644 (file)
index 0000000..34b8d38
--- /dev/null
@@ -0,0 +1,6 @@
+.global log
+log:
+       fldln2
+       fldl 4(%esp)
+       fyl2x
+       ret
diff --git a/src/math/i386/e_log10.s b/src/math/i386/e_log10.s
new file mode 100644 (file)
index 0000000..7f48941
--- /dev/null
@@ -0,0 +1,6 @@
+.global log10
+log10:
+       fldlg2
+       fldl 4(%esp)
+       fyl2x
+       ret
diff --git a/src/math/i386/e_log10f.s b/src/math/i386/e_log10f.s
new file mode 100644 (file)
index 0000000..311486e
--- /dev/null
@@ -0,0 +1,6 @@
+.global log10f
+log10f:
+       fldlg2
+       flds 4(%esp)
+       fyl2x
+       ret
diff --git a/src/math/i386/e_logf.s b/src/math/i386/e_logf.s
new file mode 100644 (file)
index 0000000..b8beec0
--- /dev/null
@@ -0,0 +1,6 @@
+.global logf
+logf:
+       fldln2
+       flds 4(%esp)
+       fyl2x
+       ret
diff --git a/src/math/i386/e_remainder.s b/src/math/i386/e_remainder.s
new file mode 100644 (file)
index 0000000..b7ff3ef
--- /dev/null
@@ -0,0 +1,16 @@
+.global remainderf
+remainderf:
+       flds 8(%esp)
+       flds 4(%esp)
+       jmp 1f
+       
+.global remainder
+remainder:
+       fldl 12(%esp)
+       fldl 4(%esp)
+1:     fprem1
+       fstsw %ax
+       sahf
+       jp 1b
+       fstp %st(1)
+       ret
diff --git a/src/math/i386/e_remainderf.s b/src/math/i386/e_remainderf.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/e_sqrt.s b/src/math/i386/e_sqrt.s
new file mode 100644 (file)
index 0000000..11314dc
--- /dev/null
@@ -0,0 +1,4 @@
+.global sqrt
+sqrt:  fldl 4(%esp)
+       fsqrt
+       ret
diff --git a/src/math/i386/e_sqrtf.s b/src/math/i386/e_sqrtf.s
new file mode 100644 (file)
index 0000000..015e24c
--- /dev/null
@@ -0,0 +1,4 @@
+.global sqrtf
+sqrtf: flds 4(%esp)
+       fsqrt
+       ret
diff --git a/src/math/i386/s_ceil.s b/src/math/i386/s_ceil.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/s_ceilf.s b/src/math/i386/s_ceilf.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/s_fabs.s b/src/math/i386/s_fabs.s
new file mode 100644 (file)
index 0000000..10c70f3
--- /dev/null
@@ -0,0 +1,5 @@
+.global fabs
+fabs:
+       fldl 4(%esp)
+       fabs
+       ret
diff --git a/src/math/i386/s_fabsf.s b/src/math/i386/s_fabsf.s
new file mode 100644 (file)
index 0000000..4544269
--- /dev/null
@@ -0,0 +1,5 @@
+.global fabsf
+fabsf:
+       flds 4(%esp)
+       fabs
+       ret
diff --git a/src/math/i386/s_floor.s b/src/math/i386/s_floor.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/s_floorf.s b/src/math/i386/s_floorf.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/s_ldexp.s b/src/math/i386/s_ldexp.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/s_ldexpf.s b/src/math/i386/s_ldexpf.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/i386/s_rint.s b/src/math/i386/s_rint.s
new file mode 100644 (file)
index 0000000..5ba4ab4
--- /dev/null
@@ -0,0 +1,5 @@
+.global rint
+rint:
+       fldl 4(%esp)
+       frndint
+       ret
diff --git a/src/math/i386/s_rintf.s b/src/math/i386/s_rintf.s
new file mode 100644 (file)
index 0000000..d7aacd8
--- /dev/null
@@ -0,0 +1,5 @@
+.global rintf
+rintf:
+       flds 4(%esp)
+       frndint
+       ret
diff --git a/src/math/i386/s_scalbln.s b/src/math/i386/s_scalbln.s
new file mode 100644 (file)
index 0000000..bd022b4
--- /dev/null
@@ -0,0 +1,11 @@
+.global ldexp
+.global scalbn
+.global scalbln
+ldexp:
+scalbn:
+scalbln:
+       fildl 12(%esp)
+       fldl 4(%esp)
+       fscale
+       fstp %st(1)
+       ret
diff --git a/src/math/i386/s_scalblnf.s b/src/math/i386/s_scalblnf.s
new file mode 100644 (file)
index 0000000..379ec91
--- /dev/null
@@ -0,0 +1,11 @@
+.global ldexpf
+.global scalbnf
+.global scalblnf
+ldexpf:
+scalbnf:
+scalblnf:
+       fildl 8(%esp)
+       flds 4(%esp)
+       fscale
+       fstp %st(1)
+       ret
diff --git a/src/math/i386/s_trunc.s b/src/math/i386/s_trunc.s
new file mode 100644 (file)
index 0000000..0773891
--- /dev/null
@@ -0,0 +1,36 @@
+.global ceilf
+ceilf: flds 4(%esp)
+       jmp 1f
+       
+.global ceil
+ceil:  fldl 4(%esp)
+1:     mov $0x08fb,%edx
+       jmp 0f
+
+.global floorf
+floorf:        flds 4(%esp)
+       jmp 1f
+
+.global floor
+floor: fldl 4(%esp)
+1:     mov $0x04f7,%edx
+       jmp 0f
+
+.global truncf
+truncf:        flds 4(%esp)
+       jmp 1f
+
+.global trunc
+trunc: fldl 4(%esp)
+1:     mov $0x0cff,%edx
+
+0:     fstcw 4(%esp)
+       mov 5(%esp),%ah
+       or %dh,%ah
+       and %dl,%ah
+       xchg %ah,5(%esp)
+       fldcw 4(%esp)
+       frndint
+       mov %ah,5(%esp)
+       fldcw 4(%esp)
+       ret
diff --git a/src/math/i386/s_truncf.s b/src/math/i386/s_truncf.s
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/math/k_cos.c b/src/math/k_cos.c
new file mode 100644 (file)
index 0000000..22e9841
--- /dev/null
@@ -0,0 +1,85 @@
+
+/* @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * __kernel_cos( x,  y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x. 
+ *
+ * Algorithm
+ *      1. Since cos(-x) = cos(x), we need only to consider positive x.
+ *      2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ *      3. cos(x) is approximated by a polynomial of degree 14 on
+ *         [0,pi/4]
+ *                                       4            14
+ *              cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ *         where the remez error is
+ *      
+ *      |              2     4     6     8     10    12     14 |     -58
+ *      |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
+ *      |                                                      | 
+ * 
+ *                     4     6     8     10    12     14 
+ *      4. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
+ *             cos(x) = 1 - x*x/2 + r
+ *         since cos(x+y) ~ cos(x) - sin(x)*y 
+ *                        ~ cos(x) - x*y,
+ *         a correction term is necessary in cos(x) and hence
+ *              cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ *         For better accuracy when x > 0.3, let qx = |x|/4 with
+ *         the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+ *         Then
+ *              cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+ *         Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+ *         magnitude of the latter is at least a quarter of x*x/2,
+ *         thus, reducing the rounding error in the subtraction.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5  =  2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6  = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+double
+__kernel_cos(double x, double y)
+{
+        double a,hz,z,r,qx;
+        int32_t ix;
+        GET_HIGH_WORD(ix,x);
+        ix &= 0x7fffffff;                       /* ix = |x|'s high word*/
+        if(ix<0x3e400000) {                     /* if x < 2**27 */
+            if(((int)x)==0) return one;         /* generate inexact */
+        }
+        z  = x*x;
+        r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+        if(ix < 0x3FD33333)                     /* if |x| < 0.3 */ 
+            return one - (0.5*z - (z*r - x*y));
+        else {
+            if(ix > 0x3fe90000) {               /* x > 0.78125 */
+                qx = 0.28125;
+            } else {
+                INSERT_WORDS(qx,ix-0x00200000,0);       /* x/4 */
+            }
+            hz = 0.5*z-qx;
+            a  = one-qx;
+            return a - (hz - (z*r-x*y));
+        }
+}
diff --git a/src/math/k_cosf.c b/src/math/k_cosf.c
new file mode 100644 (file)
index 0000000..61dc374
--- /dev/null
@@ -0,0 +1,52 @@
+/* k_cosf.c -- float version of k_cos.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3f800000 */
+C1  =  4.1666667908e-02, /* 0x3d2aaaab */
+C2  = -1.3888889225e-03, /* 0xbab60b61 */
+C3  =  2.4801587642e-05, /* 0x37d00d01 */
+C4  = -2.7557314297e-07, /* 0xb493f27c */
+C5  =  2.0875723372e-09, /* 0x310f74f6 */
+C6  = -1.1359647598e-11; /* 0xad47d74e */
+
+float
+__kernel_cosf(float x, float y)
+{
+        float a,hz,z,r,qx;
+        int32_t ix;
+        GET_FLOAT_WORD(ix,x);
+        ix &= 0x7fffffff;                       /* ix = |x|'s high word*/
+        if(ix<0x32000000) {                     /* if x < 2**27 */
+            if(((int)x)==0) return one;         /* generate inexact */
+        }
+        z  = x*x;
+        r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+        if(ix < 0x3e99999a)                     /* if |x| < 0.3 */
+            return one - ((float)0.5*z - (z*r - x*y));
+        else {
+            if(ix > 0x3f480000) {               /* x > 0.78125 */
+                qx = (float)0.28125;
+            } else {
+                SET_FLOAT_WORD(qx,ix-0x01000000);       /* x/4 */
+            }
+            hz = (float)0.5*z-qx;
+            a  = one-qx;
+            return a - (hz - (z*r-x*y));
+        }
+}
diff --git a/src/math/k_rem_pio2.c b/src/math/k_rem_pio2.c
new file mode 100644 (file)
index 0000000..d993e4f
--- /dev/null
@@ -0,0 +1,300 @@
+
+/* @(#)k_rem_pio2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ * double x[],y[]; int e0,nx,prec; int ipio2[];
+ * 
+ * __kernel_rem_pio2 return the last three digits of N with 
+ *              y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of 
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ *      x[]     The input value (must be positive) is broken into nx 
+ *              pieces of 24-bit integers in double precision format.
+ *              x[i] will be the i-th 24 bit of x. The scaled exponent 
+ *              of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 
+ *              match x's up to 24 bits.
+ *
+ *              Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ *                      e0 = ilogb(z)-23
+ *                      z  = scalbn(z,-e0)
+ *              for i = 0,1,2
+ *                      x[i] = floor(z)
+ *                      z    = (z-x[i])*2**24
+ *
+ *
+ *      y[]     ouput result in an array of double precision numbers.
+ *              The dimension of y[] is:
+ *                      24-bit  precision       1
+ *                      53-bit  precision       2
+ *                      64-bit  precision       2
+ *                      113-bit precision       3
+ *              The actual value is the sum of them. Thus for 113-bit
+ *              precison, one may have to do something like:
+ *
+ *              long double t,w,r_head, r_tail;
+ *              t = (long double)y[2] + (long double)y[1];
+ *              w = (long double)y[0];
+ *              r_head = t+w;
+ *              r_tail = w - (r_head - t);
+ *
+ *      e0      The exponent of x[0]
+ *
+ *      nx      dimension of x[]
+ *
+ *      prec    an integer indicating the precision:
+ *                      0       24  bits (single)
+ *                      1       53  bits (double)
+ *                      2       64  bits (extended)
+ *                      3       113 bits (quad)
+ *
+ *      ipio2[]
+ *              integer array, contains the (24*i)-th to (24*i+23)-th 
+ *              bit of 2/pi after binary point. The corresponding 
+ *              floating value is
+ *
+ *                      ipio2[i] * 2^(-24(i+1)).
+ *
+ * External function:
+ *      double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ *      jk      jk+1 is the initial number of terms of ipio2[] needed
+ *              in the computation. The recommended value is 2,3,4,
+ *              6 for single, double, extended,and quad.
+ *
+ *      jz      local integer variable indicating the number of 
+ *              terms of ipio2[] used. 
+ *
+ *      jx      nx - 1
+ *
+ *      jv      index for pointing to the suitable ipio2[] for the
+ *              computation. In general, we want
+ *                      ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ *              is an integer. Thus
+ *                      e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ *              Hence jv = max(0,(e0-3)/24).
+ *
+ *      jp      jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ *      q[]     double array with integral value, representing the
+ *              24-bits chunk of the product of x and 2/pi.
+ *
+ *      q0      the corresponding exponent of q[0]. Note that the
+ *              exponent for q[i] would be q0-24*i.
+ *
+ *      PIo2[]  double precision array, obtained by cutting pi/2
+ *              into 24 bits chunks. 
+ *
+ *      f[]     ipio2[] in floating point 
+ *
+ *      iq[]    integer array by breaking up q[] in 24-bits chunk.
+ *
+ *      fq[]    final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ *      ih      integer. If >0 it indicates q[] is >= 0.5, hence
+ *              it also indicates the *sign* of the result.
+ *
+ */
+
+
+/*
+ * 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 <math.h>
+#include "math_private.h"
+
+static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
+
+static const double PIo2[] = {
+  1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+  7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+  5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+  3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+  1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+  1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+  2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+  2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+};
+
+static const double                     
+zero   = 0.0,
+one    = 1.0,
+two24   =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+twon24  =  5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+        int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
+{
+        int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+        double z,fw,f[20],fq[20],q[20];
+
+    /* initialize jk*/
+        jk = init_jk[prec];
+        jp = jk;
+
+    /* determine jx,jv,q0, note that 3>q0 */
+        jx =  nx-1;
+        jv = (e0-3)/24; if(jv<0) jv=0;
+        q0 =  e0-24*(jv+1);
+
+    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+        j = jv-jx; m = jx+jk;
+        for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+
+    /* compute q[0],q[1],...q[jk] */
+        for (i=0;i<=jk;i++) {
+            for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+        }
+
+        jz = jk;
+recompute:
+    /* distill q[] into iq[] reversingly */
+        for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+            fw    =  (double)((int32_t)(twon24* z));
+            iq[i] =  (int32_t)(z-two24*fw);
+            z     =  q[j-1]+fw;
+        }
+
+    /* compute n */
+        z  = scalbn(z,q0);              /* actual value of z */
+        z -= 8.0*floor(z*0.125);                /* trim off integer >= 8 */
+        n  = (int32_t) z;
+        z -= (double)n;
+        ih = 0;
+        if(q0>0) {      /* need iq[jz-1] to determine n */
+            i  = (iq[jz-1]>>(24-q0)); n += i;
+            iq[jz-1] -= i<<(24-q0);
+            ih = iq[jz-1]>>(23-q0);
+        } 
+        else if(q0==0) ih = iq[jz-1]>>23;
+        else if(z>=0.5) ih=2;
+
+        if(ih>0) {      /* q > 0.5 */
+            n += 1; carry = 0;
+            for(i=0;i<jz ;i++) {        /* compute 1-q */
+                j = iq[i];
+                if(carry==0) {
+                    if(j!=0) {
+                        carry = 1; iq[i] = 0x1000000- j;
+                    }
+                } else  iq[i] = 0xffffff - j;
+            }
+            if(q0>0) {          /* rare case: chance is 1 in 12 */
+                switch(q0) {
+                case 1:
+                   iq[jz-1] &= 0x7fffff; break;
+                case 2:
+                   iq[jz-1] &= 0x3fffff; break;
+                }
+            }
+            if(ih==2) {
+                z = one - z;
+                if(carry!=0) z -= scalbn(one,q0);
+            }
+        }
+
+    /* check if recomputation is needed */
+        if(z==zero) {
+            j = 0;
+            for (i=jz-1;i>=jk;i--) j |= iq[i];
+            if(j==0) { /* need recomputation */
+                for(k=1;iq[jk-k]==0;k++);   /* k = no. of terms needed */
+
+                for(i=jz+1;i<=jz+k;i++) {   /* add q[jz+1] to q[jz+k] */
+                    f[jx+i] = (double) ipio2[jv+i];
+                    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+                    q[i] = fw;
+                }
+                jz += k;
+                goto recompute;
+            }
+        }
+
+    /* chop off zero terms */
+        if(z==0.0) {
+            jz -= 1; q0 -= 24;
+            while(iq[jz]==0) { jz--; q0-=24;}
+        } else { /* break z into 24-bit if necessary */
+            z = scalbn(z,-q0);
+            if(z>=two24) { 
+                fw = (double)((int32_t)(twon24*z));
+                iq[jz] = (int32_t)(z-two24*fw);
+                jz += 1; q0 += 24;
+                iq[jz] = (int32_t) fw;
+            } else iq[jz] = (int32_t) z ;
+        }
+
+    /* convert integer "bit" chunk to floating-point value */
+        fw = scalbn(one,q0);
+        for(i=jz;i>=0;i--) {
+            q[i] = fw*(double)iq[i]; fw*=twon24;
+        }
+
+    /* compute PIo2[0,...,jp]*q[jz,...,0] */
+        for(i=jz;i>=0;i--) {
+            for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+            fq[jz-i] = fw;
+        }
+
+    /* compress fq[] into y[] */
+        switch(prec) {
+            case 0:
+                fw = 0.0;
+                for (i=jz;i>=0;i--) fw += fq[i];
+                y[0] = (ih==0)? fw: -fw; 
+                break;
+            case 1:
+            case 2:
+                fw = 0.0;
+                for (i=jz;i>=0;i--) fw += fq[i]; 
+                y[0] = (ih==0)? fw: -fw; 
+                fw = fq[0]-fw;
+                for (i=1;i<=jz;i++) fw += fq[i];
+                y[1] = (ih==0)? fw: -fw; 
+                break;
+            case 3:     /* painful */
+                for (i=jz;i>0;i--) {
+                    fw      = fq[i-1]+fq[i]; 
+                    fq[i]  += fq[i-1]-fw;
+                    fq[i-1] = fw;
+                }
+                for (i=jz;i>1;i--) {
+                    fw      = fq[i-1]+fq[i]; 
+                    fq[i]  += fq[i-1]-fw;
+                    fq[i-1] = fw;
+                }
+                for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; 
+                if(ih==0) {
+                    y[0] =  fq[0]; y[1] =  fq[1]; y[2] =  fw;
+                } else {
+                    y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+                }
+        }
+        return n&7;
+}
diff --git a/src/math/k_rem_pio2f.c b/src/math/k_rem_pio2f.c
new file mode 100644 (file)
index 0000000..b543f08
--- /dev/null
@@ -0,0 +1,192 @@
+/* k_rem_pio2f.c -- float version of k_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/* In the float version, the input parameter x contains 8 bit
+   integers, not 24 bit integers.  113 bit precision is not supported.  */
+
+static const int init_jk[] = {4,7,9}; /* initial value for jk */
+
+static const float PIo2[] = {
+  1.5703125000e+00, /* 0x3fc90000 */
+  4.5776367188e-04, /* 0x39f00000 */
+  2.5987625122e-05, /* 0x37da0000 */
+  7.5437128544e-08, /* 0x33a20000 */
+  6.0026650317e-11, /* 0x2e840000 */
+  7.3896444519e-13, /* 0x2b500000 */
+  5.3845816694e-15, /* 0x27c20000 */
+  5.6378512969e-18, /* 0x22d00000 */
+  8.3009228831e-20, /* 0x1fc40000 */
+  3.2756352257e-22, /* 0x1bc60000 */
+  6.3331015649e-25, /* 0x17440000 */
+};
+
+static const float
+zero   = 0.0,
+one    = 1.0,
+two8   =  2.5600000000e+02, /* 0x43800000 */
+twon8  =  3.9062500000e-03; /* 0x3b800000 */
+
+        int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32_t *ipio2)
+{
+        int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+        float z,fw,f[20],fq[20],q[20];
+
+    /* initialize jk*/
+        jk = init_jk[prec];
+        jp = jk;
+
+    /* determine jx,jv,q0, note that 3>q0 */
+        jx =  nx-1;
+        jv = (e0-3)/8; if(jv<0) jv=0;
+        q0 =  e0-8*(jv+1);
+
+    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+        j = jv-jx; m = jx+jk;
+        for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
+
+    /* compute q[0],q[1],...q[jk] */
+        for (i=0;i<=jk;i++) {
+            for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+        }
+
+        jz = jk;
+recompute:
+    /* distill q[] into iq[] reversingly */
+        for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+            fw    =  (float)((int32_t)(twon8* z));
+            iq[i] =  (int32_t)(z-two8*fw);
+            z     =  q[j-1]+fw;
+        }
+
+    /* compute n */
+        z  = scalbnf(z,q0);             /* actual value of z */
+        z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */
+        n  = (int32_t) z;
+        z -= (float)n;
+        ih = 0;
+        if(q0>0) {      /* need iq[jz-1] to determine n */
+            i  = (iq[jz-1]>>(8-q0)); n += i;
+            iq[jz-1] -= i<<(8-q0);
+            ih = iq[jz-1]>>(7-q0);
+        }
+        else if(q0==0) ih = iq[jz-1]>>7;
+        else if(z>=(float)0.5) ih=2;
+
+        if(ih>0) {      /* q > 0.5 */
+            n += 1; carry = 0;
+            for(i=0;i<jz ;i++) {        /* compute 1-q */
+                j = iq[i];
+                if(carry==0) {
+                    if(j!=0) {
+                        carry = 1; iq[i] = 0x100- j;
+                    }
+                } else  iq[i] = 0xff - j;
+            }
+            if(q0>0) {          /* rare case: chance is 1 in 12 */
+                switch(q0) {
+                case 1:
+                   iq[jz-1] &= 0x7f; break;
+                case 2:
+                   iq[jz-1] &= 0x3f; break;
+                }
+            }
+            if(ih==2) {
+                z = one - z;
+                if(carry!=0) z -= scalbnf(one,q0);
+            }
+        }
+
+    /* check if recomputation is needed */
+        if(z==zero) {
+            j = 0;
+            for (i=jz-1;i>=jk;i--) j |= iq[i];
+            if(j==0) { /* need recomputation */
+                for(k=1;iq[jk-k]==0;k++);   /* k = no. of terms needed */
+
+                for(i=jz+1;i<=jz+k;i++) {   /* add q[jz+1] to q[jz+k] */
+                    f[jx+i] = (float) ipio2[jv+i];
+                    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+                    q[i] = fw;
+                }
+                jz += k;
+                goto recompute;
+            }
+        }
+
+    /* chop off zero terms */
+        if(z==(float)0.0) {
+            jz -= 1; q0 -= 8;
+            while(iq[jz]==0) { jz--; q0-=8;}
+        } else { /* break z into 8-bit if necessary */
+            z = scalbnf(z,-q0);
+            if(z>=two8) {
+                fw = (float)((int32_t)(twon8*z));
+                iq[jz] = (int32_t)(z-two8*fw);
+                jz += 1; q0 += 8;
+                iq[jz] = (int32_t) fw;
+            } else iq[jz] = (int32_t) z ;
+        }
+
+    /* convert integer "bit" chunk to floating-point value */
+        fw = scalbnf(one,q0);
+        for(i=jz;i>=0;i--) {
+            q[i] = fw*(float)iq[i]; fw*=twon8;
+        }
+
+    /* compute PIo2[0,...,jp]*q[jz,...,0] */
+        for(i=jz;i>=0;i--) {
+            for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+            fq[jz-i] = fw;
+        }
+
+    /* compress fq[] into y[] */
+        switch(prec) {
+            case 0:
+                fw = 0.0;
+                for (i=jz;i>=0;i--) fw += fq[i];
+                y[0] = (ih==0)? fw: -fw;
+                break;
+            case 1:
+            case 2:
+                fw = 0.0;
+                for (i=jz;i>=0;i--) fw += fq[i];
+                y[0] = (ih==0)? fw: -fw;
+                fw = fq[0]-fw;
+                for (i=1;i<=jz;i++) fw += fq[i];
+                y[1] = (ih==0)? fw: -fw;
+                break;
+            case 3:     /* painful */
+                for (i=jz;i>0;i--) {
+                    fw      = fq[i-1]+fq[i];
+                    fq[i]  += fq[i-1]-fw;
+                    fq[i-1] = fw;
+                }
+                for (i=jz;i>1;i--) {
+                    fw      = fq[i-1]+fq[i];
+                    fq[i]  += fq[i-1]-fw;
+                    fq[i-1] = fw;
+                }
+                for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+                if(ih==0) {
+                    y[0] =  fq[0]; y[1] =  fq[1]; y[2] =  fw;
+                } else {
+                    y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+                }
+        }
+        return n&7;
+}
diff --git a/src/math/k_sin.c b/src/math/k_sin.c
new file mode 100644 (file)
index 0000000..9def258
--- /dev/null
@@ -0,0 +1,68 @@
+
+/* @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). 
+ *
+ * Algorithm
+ *      1. Since sin(-x) = -sin(x), we need only to consider positive x. 
+ *      2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+ *      3. sin(x) is approximated by a polynomial of degree 13 on
+ *         [0,pi/4]
+ *                               3            13
+ *              sin(x) ~ x + S1*x + ... + S6*x
+ *         where
+ *      
+ *      |sin(x)         2     4     6     8     10     12  |     -58
+ *      |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
+ *      |  x                                               | 
+ * 
+ *      4. sin(x+y) = sin(x) + sin'(x')*y
+ *                  ~ sin(x) + (1-x*x/2)*y
+ *         For better accuracy, let 
+ *                   3      2      2      2      2
+ *              r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ *         then                   3    2
+ *              sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5  = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6  =  1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+
+double
+__kernel_sin(double x, double y, int iy)
+{
+        double z,r,v;
+        int32_t ix;
+        GET_HIGH_WORD(ix,x);
+        ix &= 0x7fffffff;                       /* high word of x */
+        if(ix<0x3e400000)                       /* |x| < 2**-27 */
+           {if((int)x==0) return x;}            /* generate inexact */
+        z       =  x*x;
+        v       =  z*x;
+        r       =  S2+z*(S3+z*(S4+z*(S5+z*S6)));
+        if(iy==0) return x+v*(S1+z*r);
+        else      return x-((z*(half*y-v*r)-y)-v*S1);
+}
diff --git a/src/math/k_sinf.c b/src/math/k_sinf.c
new file mode 100644 (file)
index 0000000..617f614
--- /dev/null
@@ -0,0 +1,42 @@
+/* k_sinf.c -- float version of k_sin.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+half =  5.0000000000e-01,/* 0x3f000000 */
+S1  = -1.6666667163e-01, /* 0xbe2aaaab */
+S2  =  8.3333337680e-03, /* 0x3c088889 */
+S3  = -1.9841270114e-04, /* 0xb9500d01 */
+S4  =  2.7557314297e-06, /* 0x3638ef1b */
+S5  = -2.5050759689e-08, /* 0xb2d72f34 */
+S6  =  1.5896910177e-10; /* 0x2f2ec9d3 */
+
+float
+__kernel_sinf(float x, float y, int iy)
+{
+        float z,r,v;
+        int32_t ix;
+        GET_FLOAT_WORD(ix,x);
+        ix &= 0x7fffffff;                       /* high word of x */
+        if(ix<0x32000000)                       /* |x| < 2**-27 */
+           {if((int)x==0) return x;}            /* generate inexact */
+        z       =  x*x;
+        v       =  z*x;
+        r       =  S2+z*(S3+z*(S4+z*(S5+z*S6)));
+        if(iy==0) return x+v*(S1+z*r);
+        else      return x-((z*(half*y-v*r)-y)-v*S1);
+}
diff --git a/src/math/k_tan.c b/src/math/k_tan.c
new file mode 100644 (file)
index 0000000..f721ae6
--- /dev/null
@@ -0,0 +1,149 @@
+/* @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
+ *
+ * Algorithm
+ *      1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ *      2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+ *      3. tan(x) is approximated by a odd polynomial of degree 27 on
+ *         [0,0.67434]
+ *                               3             27
+ *              tan(x) ~ x + T1*x + ... + T13*x
+ *         where
+ *
+ *              |tan(x)         2     4            26   |     -59.2
+ *              |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
+ *              |  x                                    |
+ *
+ *         Note: tan(x+y) = tan(x) + tan'(x)*y
+ *                        ~ tan(x) + (1+x*x)*y
+ *         Therefore, for better accuracy in computing tan(x+y), let
+ *                   3      2      2       2       2
+ *              r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ *         then
+ *                                  3    2
+ *              tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
+ *              tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ *                     = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+#include <math.h>
+#include "math_private.h"
+static const double xxx[] = {
+                 3.33333333333334091986e-01,    /* 3FD55555, 55555563 */
+                 1.33333333333201242699e-01,    /* 3FC11111, 1110FE7A */
+                 5.39682539762260521377e-02,    /* 3FABA1BA, 1BB341FE */
+                 2.18694882948595424599e-02,    /* 3F9664F4, 8406D637 */
+                 8.86323982359930005737e-03,    /* 3F8226E3, E96E8493 */
+                 3.59207910759131235356e-03,    /* 3F6D6D22, C9560328 */
+                 1.45620945432529025516e-03,    /* 3F57DBC8, FEE08315 */
+                 5.88041240820264096874e-04,    /* 3F4344D8, F2F26501 */
+                 2.46463134818469906812e-04,    /* 3F3026F7, 1A8D1068 */
+                 7.81794442939557092300e-05,    /* 3F147E88, A03792A6 */
+                 7.14072491382608190305e-05,    /* 3F12B80F, 32F0A7E9 */
+                -1.85586374855275456654e-05,    /* BEF375CB, DB605373 */
+                 2.59073051863633712884e-05,    /* 3EFB2A70, 74BF7AD4 */
+/* one */        1.00000000000000000000e+00,    /* 3FF00000, 00000000 */
+/* pio4 */       7.85398163397448278999e-01,    /* 3FE921FB, 54442D18 */
+/* pio4lo */     3.06161699786838301793e-17     /* 3C81A626, 33145C07 */
+};
+#define one     xxx[13]
+#define pio4    xxx[14]
+#define pio4lo  xxx[15]
+#define T       xxx
+/* INDENT ON */
+
+double
+__kernel_tan(double x, double y, int iy) {
+        double z, r, v, w, s;
+        int32_t ix, hx;
+
+        GET_HIGH_WORD(hx,x);
+        ix = hx & 0x7fffffff;                   /* high word of |x| */
+        if (ix < 0x3e300000) {                  /* x < 2**-28 */
+                if ((int) x == 0) {             /* generate inexact */
+                        uint32_t low;
+                        GET_LOW_WORD(low,x);
+                        if (((ix | low) | (iy + 1)) == 0)
+                                return one / fabs(x);
+                        else {
+                                if (iy == 1)
+                                        return x;
+                                else {  /* compute -1 / (x+y) carefully */
+                                        double a, t;
+
+                                        z = w = x + y;
+                                        SET_LOW_WORD(z, 0);
+                                        v = y - (z - x);
+                                        t = a = -one / w;
+                                        SET_LOW_WORD(t, 0);
+                                        s = one + t * z;
+                                        return t + a * (s + t * v);
+                                }
+                        }
+                }
+        }
+        if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */
+                if (hx < 0) {
+                        x = -x;
+                        y = -y;
+                }
+                z = pio4 - x;
+                w = pio4lo - y;
+                x = z + w;
+                y = 0.0;
+        }
+        z = x * x;
+        w = z * z;
+        /*
+         * Break x^5*(T[1]+x^2*T[2]+...) into
+         * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+         * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+         */
+        r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] +
+                w * T[11]))));
+        v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] +
+                w * T[12])))));
+        s = z * x;
+        r = y + z * (s * (r + v) + y);
+        r += T[0] * s;
+        w = x + r;
+        if (ix >= 0x3FE59428) {
+                v = (double) iy;
+                return (double) (1 - ((hx >> 30) & 2)) *
+                        (v - 2.0 * (x - (w * w / (w + v) - r)));
+        }
+        if (iy == 1)
+                return w;
+        else {
+                /*
+                 * if allow error up to 2 ulp, simply return
+                 * -1.0 / (x+r) here
+                 */
+                /* compute -1.0 / (x+r) accurately */
+                double a, t;
+                z = w;
+                SET_LOW_WORD(z,0);
+                v = r - (z - x);        /* z+v = r+x */
+                t = a = -1.0 / w;       /* a = -1.0/w */
+                SET_LOW_WORD(t,0);
+                s = 1.0 + t * z;
+                return t + a * (s + t * v);
+        }
+}
diff --git a/src/math/k_tanf.c b/src/math/k_tanf.c
new file mode 100644 (file)
index 0000000..99ede58
--- /dev/null
@@ -0,0 +1,105 @@
+/* k_tanf.c -- float version of k_tan.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+static const float
+one   =  1.0000000000e+00, /* 0x3f800000 */
+pio4  =  7.8539812565e-01, /* 0x3f490fda */
+pio4lo=  3.7748947079e-08, /* 0x33222168 */
+T[] =  {
+  3.3333334327e-01, /* 0x3eaaaaab */
+  1.3333334029e-01, /* 0x3e088889 */
+  5.3968254477e-02, /* 0x3d5d0dd1 */
+  2.1869488060e-02, /* 0x3cb327a4 */
+  8.8632395491e-03, /* 0x3c11371f */
+  3.5920790397e-03, /* 0x3b6b6916 */
+  1.4562094584e-03, /* 0x3abede48 */
+  5.8804126456e-04, /* 0x3a1a26c8 */
+  2.4646313977e-04, /* 0x398137b9 */
+  7.8179444245e-05, /* 0x38a3f445 */
+  7.1407252108e-05, /* 0x3895c07a */
+ -1.8558637748e-05, /* 0xb79bae5f */
+  2.5907305826e-05, /* 0x37d95384 */
+};
+
+float
+__kernel_tanf(float x, float y, int iy)
+{
+        float z,r,v,w,s;
+        int32_t ix,hx;
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;     /* high word of |x| */
+        if(ix<0x31800000) {                     /* x < 2**-28 */
+                if ((int) x == 0) {             /* generate inexact */
+                        if ((ix | (iy + 1)) == 0)
+                                return one / fabsf(x);
+                        else {
+                                if (iy == 1)
+                                        return x;
+                                else {  /* compute -1 / (x+y) carefully */
+                                        double a, t;
+
+                                        z = w = x + y;
+                                        GET_FLOAT_WORD(ix, z);
+                                        SET_FLOAT_WORD(z, ix & 0xfffff000);
+                                        v = y - (z - x);
+                                        t = a = -one / w;
+                                        GET_FLOAT_WORD(ix, t);
+                                        SET_FLOAT_WORD(t, ix & 0xfffff000);
+                                        s = one + t * z;
+                                        return t + a * (s + t * v);
+                                }
+                        }
+                }
+        }
+        if(ix>=0x3f2ca140) {                    /* |x|>=0.6744 */
+            if(hx<0) {x = -x; y = -y;}
+            z = pio4-x;
+            w = pio4lo-y;
+            x = z+w; y = 0.0;
+        }
+        z       =  x*x;
+        w       =  z*z;
+    /* Break x^5*(T[1]+x^2*T[2]+...) into
+     *    x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+     *    x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+     */
+        r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
+        v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+        s = z*x;
+        r = y + z*(s*(r+v)+y);
+        r += T[0]*s;
+        w = x+r;
+        if(ix>=0x3f2ca140) {
+            v = (float)iy;
+            return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
+        }
+        if(iy==1) return w;
+        else {          /* if allow error up to 2 ulp,
+                           simply return -1.0/(x+r) here */
+     /*  compute -1.0/(x+r) accurately */
+            float a,t;
+            int32_t i;
+            z  = w;
+            GET_FLOAT_WORD(i,z);
+            SET_FLOAT_WORD(z,i&0xfffff000);
+            v  = r-(z - x);     /* z+v = r+x */
+            t = a  = -(float)1.0/w;     /* a = -1.0/w */
+            GET_FLOAT_WORD(i,t);
+            SET_FLOAT_WORD(t,i&0xfffff000);
+            s  = (float)1.0+t*z;
+            return t+a*(s+t*v);
+        }
+}
diff --git a/src/math/math_private.h b/src/math/math_private.h
new file mode 100644 (file)
index 0000000..28a6a19
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#ifndef _MATH_PRIVATE_H_
+#define _MATH_PRIVATE_H_
+
+#include <inttypes.h>
+
+/*
+ * The original fdlibm code used statements like:
+ *      n0 = ((*(int*)&one)>>29)^1;             * index of high word *
+ *      ix0 = *(n0+(int*)&x);                   * high word of x *
+ *      ix1 = *((1-n0)+(int*)&x);               * low word of x *
+ * to dig two 32 bit words out of the 64 bit IEEE floating point
+ * value.  That is non-ANSI, and, moreover, the gcc instruction
+ * scheduler gets it wrong.  We instead use the following macros.
+ * Unlike the original code, we determine the endianness at compile
+ * time, not at run time; I don't see much benefit to selecting
+ * endianness at run time.
+ */
+
+/*
+ * A union which permits us to convert between a double and two 32 bit
+ * ints.
+ */
+
+typedef union
+{
+  double value;
+  uint64_t words;
+} ieee_double_shape_type;
+
+/* Get two 32 bit ints from a double.  */
+
+#define EXTRACT_WORDS(ix0,ix1,d)                                \
+do {                                                            \
+  ieee_double_shape_type ew_u;                                  \
+  ew_u.value = (d);                                             \
+  (ix0) = ew_u.words >> 32;                                     \
+  (ix1) = (uint32_t)ew_u.words;                                 \
+} while (0)
+
+/* Get the more significant 32 bit int from a double.  */
+
+#define GET_HIGH_WORD(i,d)                                      \
+do {                                                            \
+  ieee_double_shape_type gh_u;                                  \
+  gh_u.value = (d);                                             \
+  (i) = gh_u.words >> 32;                                       \
+} while (0)
+
+/* Get the less significant 32 bit int from a double.  */
+
+#define GET_LOW_WORD(i,d)                                       \
+do {                                                            \
+  ieee_double_shape_type gl_u;                                  \
+  gl_u.value = (d);                                             \
+  (i) = (uint32_t)gl_u.words;                                   \
+} while (0)
+
+/* Set a double from two 32 bit ints.  */
+
+#define INSERT_WORDS(d,ix0,ix1)                                 \
+do {                                                            \
+  ieee_double_shape_type iw_u;                                  \
+  iw_u.words = ((uint64_t)(ix0) << 32) | (ix1);                 \
+  (d) = iw_u.value;                                             \
+} while (0)
+
+/* Set the more significant 32 bits of a double from an int.  */
+
+#define SET_HIGH_WORD(d,v)                                      \
+do {                                                            \
+  ieee_double_shape_type sh_u;                                  \
+  sh_u.value = (d);                                             \
+  sh_u.words &= 0xffffffff;                                     \
+  sh_u.words |= ((uint64_t)(v) << 32);                          \
+  (d) = sh_u.value;                                             \
+} while (0)
+
+/* Set the less significant 32 bits of a double from an int.  */
+
+#define SET_LOW_WORD(d,v)                                       \
+do {                                                            \
+  ieee_double_shape_type sl_u;                                  \
+  sl_u.value = (d);                                             \
+  sl_u.words &= 0xffffffff00000000ull;                          \
+  sl_u.words |= (uint32_t)(v);                                  \
+  (d) = sl_u.value;                                             \
+} while (0)
+
+/*
+ * A union which permits us to convert between a float and a 32 bit
+ * int.
+ */
+
+typedef union
+{
+  float value;
+  uint32_t word;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float.  */
+
+#define GET_FLOAT_WORD(i,d)                                     \
+do {                                                            \
+  ieee_float_shape_type gf_u;                                   \
+  gf_u.value = (d);                                             \
+  (i) = gf_u.word;                                              \
+} while (0)
+
+/* Set a float from a 32 bit int.  */
+
+#define SET_FLOAT_WORD(d,i)                                     \
+do {                                                            \
+  ieee_float_shape_type sf_u;                                   \
+  sf_u.word = (i);                                              \
+  (d) = sf_u.value;                                             \
+} while (0)
+
+/* fdlibm kernel function */
+int     __ieee754_rem_pio2(double,double*);
+double  __kernel_sin(double,double,int);
+double  __kernel_cos(double,double);
+double  __kernel_tan(double,double,int);
+int     __kernel_rem_pio2(double*,double*,int,int,int,const int*);
+
+/* float versions of fdlibm kernel functions */
+int     __ieee754_rem_pio2f(float,float*);
+float   __kernel_sinf(float,float,int);
+float   __kernel_cosf(float,float);
+float   __kernel_tanf(float,float,int);
+int     __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
+
+#endif /* !_MATH_PRIVATE_H_ */
diff --git a/src/math/s_asinh.c b/src/math/s_asinh.c
new file mode 100644 (file)
index 0000000..2601609
--- /dev/null
@@ -0,0 +1,53 @@
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* asinh(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)*(log(x)+ln2)) for large |x|, else
+ *               := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
+ *               := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+ln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+huge=  1.00000000000000000000e+300;
+
+double
+asinh(double x)
+{
+        double t,w;
+        int32_t hx,ix;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7ff00000) return x+x;  /* x is inf or NaN */
+        if(ix< 0x3e300000) {    /* |x|<2**-28 */
+            if(huge+x>one) return x;    /* return x inexact except 0 */
+        }
+        if(ix>0x41b00000) {     /* |x| > 2**28 */
+            w = log(fabs(x))+ln2;
+        } else if (ix>0x40000000) {     /* 2**28 > |x| > 2.0 */
+            t = fabs(x);
+            w = log(2.0*t+one/(sqrt(x*x+one)+t));
+        } else {                /* 2.0 > |x| > 2**-28 */
+            t = x*x;
+            w =log1p(fabs(x)+t/(one+sqrt(one+t)));
+        }
+        if(hx>0) return w; else return -w;
+}
diff --git a/src/math/s_asinhf.c b/src/math/s_asinhf.c
new file mode 100644 (file)
index 0000000..04f8d07
--- /dev/null
@@ -0,0 +1,45 @@
+/* s_asinhf.c -- float version of s_asinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one =  1.0000000000e+00, /* 0x3F800000 */
+ln2 =  6.9314718246e-01, /* 0x3f317218 */
+huge=  1.0000000000e+30;
+
+float
+asinhf(float x)
+{
+        float t,w;
+        int32_t hx,ix;
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7f800000) return x+x;  /* x is inf or NaN */
+        if(ix< 0x31800000) {    /* |x|<2**-28 */
+            if(huge+x>one) return x;    /* return x inexact except 0 */
+        }
+        if(ix>0x4d800000) {     /* |x| > 2**28 */
+            w = logf(fabsf(x))+ln2;
+        } else if (ix>0x40000000) {     /* 2**28 > |x| > 2.0 */
+            t = fabsf(x);
+            w = logf((float)2.0*t+one/(sqrtf(x*x+one)+t));
+        } else {                /* 2.0 > |x| > 2**-28 */
+            t = x*x;
+            w =log1pf(fabsf(x)+t/(one+sqrtf(one+t)));
+        }
+        if(hx>0) return w; else return -w;
+}
diff --git a/src/math/s_atan.c b/src/math/s_atan.c
new file mode 100644 (file)
index 0000000..1faac02
--- /dev/null
@@ -0,0 +1,115 @@
+/* @(#)s_atan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* atan(x)
+ * Method
+ *   1. Reduce x to positive by atan(x) = -atan(-x).
+ *   2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ *      is further reduced to one of the following intervals and the
+ *      arctangent of t is evaluated by the corresponding formula:
+ *
+ *      [0,7/16]      atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ *      [7/16,11/16]  atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ *      [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ *      [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ *      [39/16,INF]   atan(x) = atan(INF) + atan( -1/t )
+ *
+ * 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 <math.h>
+#include "math_private.h"
+
+static const double atanhi[] = {
+  4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+  7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+  9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+  1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+};
+
+static const double atanlo[] = {
+  2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+  3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+  1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+  6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+};
+
+static const double aT[] = {
+  3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
+ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+  1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
+ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+  9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
+ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+  6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
+ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+  4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
+ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+  1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
+};
+
+        static const double
+one   = 1.0,
+huge   = 1.0e300;
+
+double
+atan(double x)
+{
+        double w,s1,s2,z;
+        int32_t ix,hx,id;
+
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x44100000) {    /* if |x| >= 2^66 */
+            uint32_t low;
+            GET_LOW_WORD(low,x);
+            if(ix>0x7ff00000||
+                (ix==0x7ff00000&&(low!=0)))
+                return x+x;             /* NaN */
+            if(hx>0) return  atanhi[3]+atanlo[3];
+            else     return -atanhi[3]-atanlo[3];
+        } if (ix < 0x3fdc0000) {        /* |x| < 0.4375 */
+            if (ix < 0x3e200000) {      /* |x| < 2^-29 */
+                if(huge+x>one) return x;        /* raise inexact */
+            }
+            id = -1;
+        } else {
+        x = fabs(x);
+        if (ix < 0x3ff30000) {          /* |x| < 1.1875 */
+            if (ix < 0x3fe60000) {      /* 7/16 <=|x|<11/16 */
+                id = 0; x = (2.0*x-one)/(2.0+x);
+            } else {                    /* 11/16<=|x|< 19/16 */
+                id = 1; x  = (x-one)/(x+one);
+            }
+        } else {
+            if (ix < 0x40038000) {      /* |x| < 2.4375 */
+                id = 2; x  = (x-1.5)/(one+1.5*x);
+            } else {                    /* 2.4375 <= |x| < 2^66 */
+                id = 3; x  = -1.0/x;
+            }
+        }}
+    /* end of argument reduction */
+        z = x*x;
+        w = z*z;
+    /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+        s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+        s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+        if (id<0) return x - x*(s1+s2);
+        else {
+            z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+            return (hx<0)? -z:z;
+        }
+}
diff --git a/src/math/s_atanf.c b/src/math/s_atanf.c
new file mode 100644 (file)
index 0000000..03067e1
--- /dev/null
@@ -0,0 +1,95 @@
+/* s_atanf.c -- float version of s_atan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float atanhi[] = {
+  4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
+  7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
+  9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
+  1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
+};
+
+static const float atanlo[] = {
+  5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
+  3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
+  3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
+  7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
+};
+
+static const float aT[] = {
+  3.3333334327e-01, /* 0x3eaaaaaa */
+ -2.0000000298e-01, /* 0xbe4ccccd */
+  1.4285714924e-01, /* 0x3e124925 */
+ -1.1111110449e-01, /* 0xbde38e38 */
+  9.0908870101e-02, /* 0x3dba2e6e */
+ -7.6918758452e-02, /* 0xbd9d8795 */
+  6.6610731184e-02, /* 0x3d886b35 */
+ -5.8335702866e-02, /* 0xbd6ef16b */
+  4.9768779427e-02, /* 0x3d4bda59 */
+ -3.6531571299e-02, /* 0xbd15a221 */
+  1.6285819933e-02, /* 0x3c8569d7 */
+};
+
+        static const float
+one   = 1.0,
+huge   = 1.0e30;
+
+float
+atanf(float x)
+{
+        float w,s1,s2,z;
+        int32_t ix,hx,id;
+
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x50800000) {    /* if |x| >= 2^34 */
+            if(ix>0x7f800000)
+                return x+x;             /* NaN */
+            if(hx>0) return  atanhi[3]+atanlo[3];
+            else     return -atanhi[3]-atanlo[3];
+        } if (ix < 0x3ee00000) {        /* |x| < 0.4375 */
+            if (ix < 0x31000000) {      /* |x| < 2^-29 */
+                if(huge+x>one) return x;        /* raise inexact */
+            }
+            id = -1;
+        } else {
+        x = fabsf(x);
+        if (ix < 0x3f980000) {          /* |x| < 1.1875 */
+            if (ix < 0x3f300000) {      /* 7/16 <=|x|<11/16 */
+                id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
+            } else {                    /* 11/16<=|x|< 19/16 */
+                id = 1; x  = (x-one)/(x+one);
+            }
+        } else {
+            if (ix < 0x401c0000) {      /* |x| < 2.4375 */
+                id = 2; x  = (x-(float)1.5)/(one+(float)1.5*x);
+            } else {                    /* 2.4375 <= |x| < 2^66 */
+                id = 3; x  = -(float)1.0/x;
+            }
+        }}
+    /* end of argument reduction */
+        z = x*x;
+        w = z*z;
+    /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+        s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+        s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+        if (id<0) return x - x*(s1+s2);
+        else {
+            z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+            return (hx<0)? -z:z;
+        }
+}
diff --git a/src/math/s_cbrt.c b/src/math/s_cbrt.c
new file mode 100644 (file)
index 0000000..8adcb19
--- /dev/null
@@ -0,0 +1,77 @@
+/* @(#)s_cbrt.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/* cbrt(x)
+ * Return cube root of x
+ */
+static const uint32_t
+        B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
+        B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+static const double
+C =  5.42857142857142815906e-01, /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
+D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+E =  1.41428571428571436819e+00, /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
+F =  1.60714285714285720630e+00, /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
+G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+double
+cbrt(double x)
+{
+        int32_t hx;
+        double r,s,t=0.0,w;
+        uint32_t sign;
+        uint32_t high,low;
+
+        GET_HIGH_WORD(hx,x);
+        sign=hx&0x80000000;             /* sign= sign(x) */
+        hx  ^=sign;
+        if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
+        GET_LOW_WORD(low,x);
+        if((hx|low)==0)
+            return(x);          /* cbrt(0) is itself */
+
+        SET_HIGH_WORD(x,hx);    /* x <- |x| */
+    /* rough cbrt to 5 bits */
+        if(hx<0x00100000)               /* subnormal number */
+          {SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */
+           t*=x; GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high/3+B2);
+          }
+        else
+          SET_HIGH_WORD(t,hx/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) */
+        GET_HIGH_WORD(high,t);
+        INSERT_WORDS(t,high+0x00000001,0);
+
+
+    /* 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-s is exact */
+        t=t+t*r;
+
+    /* retore the sign bit */
+        GET_HIGH_WORD(high,t);
+        SET_HIGH_WORD(t,high|sign);
+        return(t);
+}
diff --git a/src/math/s_cbrtf.c b/src/math/s_cbrtf.c
new file mode 100644 (file)
index 0000000..e7b46de
--- /dev/null
@@ -0,0 +1,67 @@
+/* s_cbrtf.c -- float version of s_cbrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/* cbrtf(x)
+ * Return cube root of x
+ */
+static const unsigned
+        B1 = 709958130, /* B1 = (84+2/3-0.03306235651)*2**23 */
+        B2 = 642849266; /* B2 = (76+2/3-0.03306235651)*2**23 */
+
+static const float
+C =  5.4285717010e-01, /* 19/35     = 0x3f0af8b0 */
+D = -7.0530611277e-01, /* -864/1225 = 0xbf348ef1 */
+E =  1.4142856598e+00, /* 99/70     = 0x3fb50750 */
+F =  1.6071428061e+00, /* 45/28     = 0x3fcdb6db */
+G =  3.5714286566e-01; /* 5/14      = 0x3eb6db6e */
+
+float
+cbrtf(float x)
+{
+        float r,s,t;
+        int32_t hx;
+        uint32_t sign;
+        uint32_t high;
+
+        GET_FLOAT_WORD(hx,x);
+        sign=hx&0x80000000;             /* sign= sign(x) */
+        hx  ^=sign;
+        if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */
+        if(hx==0)
+            return(x);          /* cbrt(0) is itself */
+
+        SET_FLOAT_WORD(x,hx);   /* x <- |x| */
+    /* rough cbrt to 5 bits */
+        if(hx<0x00800000)               /* subnormal number */
+          {SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */
+           t*=x; GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,high/3+B2);
+          }
+        else
+          SET_FLOAT_WORD(t,hx/3+B1);
+
+
+    /* new cbrt to 23 bits */
+        r=t*t/x;
+        s=C+r*t;
+        t*=G+F/(s+E+D/s);
+
+    /* retore the sign bit */
+        GET_FLOAT_WORD(high,t);
+        SET_FLOAT_WORD(t,high|sign);
+        return(t);
+}
diff --git a/src/math/s_ceil.c b/src/math/s_ceil.c
new file mode 100644 (file)
index 0000000..1670cad
--- /dev/null
@@ -0,0 +1,68 @@
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ceil(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *      Bit twiddling.
+ * Exception:
+ *      Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double
+ceil(double x)
+{
+        int32_t i0,i1,j0;
+        uint32_t i,j;
+        EXTRACT_WORDS(i0,i1,x);
+        j0 = ((i0>>20)&0x7ff)-0x3ff;
+        if(j0<20) {
+            if(j0<0) {  /* raise inexact if x != 0 */
+                if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+                    if(i0<0) {i0=0x80000000;i1=0;}
+                    else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
+                }
+            } else {
+                i = (0x000fffff)>>j0;
+                if(((i0&i)|i1)==0) return x; /* x is integral */
+                if(huge+x>0.0) {        /* raise inexact flag */
+                    if(i0>0) i0 += (0x00100000)>>j0;
+                    i0 &= (~i); i1=0;
+                }
+            }
+        } else if (j0>51) {
+            if(j0==0x400) return x+x;   /* inf or NaN */
+            else return x;              /* x is integral */
+        } else {
+            i = ((uint32_t)(0xffffffff))>>(j0-20);
+            if((i1&i)==0) return x;     /* x is integral */
+            if(huge+x>0.0) {            /* raise inexact flag */
+                if(i0>0) {
+                    if(j0==20) i0+=1;
+                    else {
+                        j = i1 + (1<<(52-j0));
+                        if(j<i1) i0+=1; /* got a carry */
+                        i1 = j;
+                    }
+                }
+                i1 &= (~i);
+            }
+        }
+        INSERT_WORDS(x,i0,i1);
+        return x;
+}
diff --git a/src/math/s_ceilf.c b/src/math/s_ceilf.c
new file mode 100644 (file)
index 0000000..3615041
--- /dev/null
@@ -0,0 +1,49 @@
+/* s_ceilf.c -- float version of s_ceil.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float huge = 1.0e30;
+
+float
+ceilf(float x)
+{
+        int32_t i0,j0;
+        uint32_t i;
+
+        GET_FLOAT_WORD(i0,x);
+        j0 = ((i0>>23)&0xff)-0x7f;
+        if(j0<23) {
+            if(j0<0) {  /* raise inexact if x != 0 */
+                if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+                    if(i0<0) {i0=0x80000000;}
+                    else if(i0!=0) { i0=0x3f800000;}
+                }
+            } else {
+                i = (0x007fffff)>>j0;
+                if((i0&i)==0) return x; /* x is integral */
+                if(huge+x>(float)0.0) { /* raise inexact flag */
+                    if(i0>0) i0 += (0x00800000)>>j0;
+                    i0 &= (~i);
+                }
+            }
+        } else {
+            if(j0==0x80) return x+x;    /* inf or NaN */
+            else return x;              /* x is integral */
+        }
+        SET_FLOAT_WORD(x,i0);
+        return x;
+}
diff --git a/src/math/s_copysign.c b/src/math/s_copysign.c
new file mode 100644 (file)
index 0000000..59d3877
--- /dev/null
@@ -0,0 +1,30 @@
+/* @(#)s_copysign.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * copysign(double x, double y)
+ * copysign(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+copysign(double x, double y)
+{
+        uint32_t hx,hy;
+        GET_HIGH_WORD(hx,x);
+        GET_HIGH_WORD(hy,y);
+        SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
+        return x;
+}
diff --git a/src/math/s_copysignf.c b/src/math/s_copysignf.c
new file mode 100644 (file)
index 0000000..d650e8e
--- /dev/null
@@ -0,0 +1,33 @@
+/* s_copysignf.c -- float version of s_copysign.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * copysignf(float x, float y)
+ * copysignf(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+copysignf(float x, float y)
+{
+        uint32_t ix,iy;
+        GET_FLOAT_WORD(ix,x);
+        GET_FLOAT_WORD(iy,y);
+        SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000));
+        return x;
+}
diff --git a/src/math/s_cos.c b/src/math/s_cos.c
new file mode 100644 (file)
index 0000000..1893ab1
--- /dev/null
@@ -0,0 +1,74 @@
+/* @(#)s_cos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ *      __kernel_sin            ... sine function on [-pi/4,pi/4]
+ *      __kernel_cos            ... cosine function on [-pi/4,pi/4]
+ *      __ieee754_rem_pio2      ... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *      in [-pi/4 , +pi/4], and let n = k mod 4.
+ *      We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *          0          S           C             T
+ *          1          C          -S            -1/T
+ *          2         -S          -C             T
+ *          3         -C           S            -1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *      TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+cos(double x)
+{
+        double y[2],z=0.0;
+        int32_t n, ix;
+
+    /* High word of x. */
+        GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+        ix &= 0x7fffffff;
+        if(ix <= 0x3fe921fb) return __kernel_cos(x,z);
+
+    /* cos(Inf or NaN) is NaN */
+        else if (ix>=0x7ff00000) return x-x;
+
+    /* argument reduction needed */
+        else {
+            n = __ieee754_rem_pio2(x,y);
+            switch(n&3) {
+                case 0: return  __kernel_cos(y[0],y[1]);
+                case 1: return -__kernel_sin(y[0],y[1],1);
+                case 2: return -__kernel_cos(y[0],y[1]);
+                default:
+                        return  __kernel_sin(y[0],y[1],1);
+            }
+        }
+}
diff --git a/src/math/s_cosf.c b/src/math/s_cosf.c
new file mode 100644 (file)
index 0000000..14b8e98
--- /dev/null
@@ -0,0 +1,47 @@
+/* s_cosf.c -- float version of s_cos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one=1.0;
+
+float
+cosf(float x)
+{
+        float y[2],z=0.0;
+        int32_t n,ix;
+
+        GET_FLOAT_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+        ix &= 0x7fffffff;
+        if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
+
+    /* cos(Inf or NaN) is NaN */
+        else if (ix>=0x7f800000) return x-x;
+
+    /* argument reduction needed */
+        else {
+            n = __ieee754_rem_pio2f(x,y);
+            switch(n&3) {
+                case 0: return  __kernel_cosf(y[0],y[1]);
+                case 1: return -__kernel_sinf(y[0],y[1],1);
+                case 2: return -__kernel_cosf(y[0],y[1]);
+                default:
+                        return  __kernel_sinf(y[0],y[1],1);
+            }
+        }
+}
diff --git a/src/math/s_erf.c b/src/math/s_erf.c
new file mode 100644 (file)
index 0000000..e321fee
--- /dev/null
@@ -0,0 +1,298 @@
+/* @(#)s_erf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ *                           x
+ *                    2      |\
+ *     erf(x)  =  ---------  | exp(-t*t)dt
+ *                 sqrt(pi) \|
+ *                           0
+ *
+ *     erfc(x) =  1-erf(x)
+ *  Note that
+ *              erf(-x) = -erf(x)
+ *              erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ *      1. For |x| in [0, 0.84375]
+ *          erf(x)  = x + x*R(x^2)
+ *          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
+ *                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
+ *         where R = P/Q where P is an odd poly of degree 8 and
+ *         Q is an odd poly of degree 10.
+ *                                               -57.90
+ *                      | R - (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 fix
+ *         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.
+ *
+ *      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ *         c = 0.84506291151 rounded to single (24 bits)
+ *              erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
+ *              erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
+ *                        1+(c+P1(s)/Q1(s))    if x < 0
+ *              |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
+ *
+ *      3. For x in [1.25,1/0.35(~2.857143)],
+ *              erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+ *              erf(x)  = 1 - erfc(x)
+ *         where
+ *              R1(z) = degree 7 poly in z, (z=1/x^2)
+ *              S1(z) = degree 8 poly in z
+ *
+ *      4. For x in [1/0.35,28]
+ *              erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ *                      = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+ *                      = 2.0 - tiny            (if x <= -6)
+ *              erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6, else
+ *              erf(x)  = sign(x)*(1.0 - tiny)
+ *         where
+ *              R2(z) = degree 6 poly in z, (z=1/x^2)
+ *              S2(z) = degree 7 poly in z
+ *
+ *      Note1:
+ *         To compute exp(-x*x-0.5625+R/S), let s be a single
+ *         precision number and s := x; then
+ *              -x*x = -s*s + (s-x)*(s+x)
+ *              exp(-x*x-0.5626+R/S) =
+ *                      exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ *      Note2:
+ *         Here 4 and 5 make use of the asymptotic series
+ *                        exp(-x*x)
+ *              erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ *                        x*sqrt(pi)
+ *         We use rational approximation to approximate
+ *              g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
+ *         Here is the error bound for R1/S1 and R2/S2
+ *              |R1/S1 - f(x)|  < 2**(-62.57)
+ *              |R2/S2 - f(x)|  < 2**(-61.52)
+ *
+ *      5. For inf > x >= 28
+ *              erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+ *              erfc(x) = tiny*tiny (raise underflow) if x > 0
+ *                      = 2 - tiny if x<0
+ *
+ *      7. Special case:
+ *              erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+ *              erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ *              erfc/erf(NaN) is NaN
+ */
+
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+tiny        = 1e-300,
+half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+two =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+        /* c = (float)0.84506291151 */
+erx =  8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
+/*
+ * Coefficients for approximation to  erf on [0,0.84375]
+ */
+efx =  1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
+efx8=  1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
+pp0  =  1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
+pp1  = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
+pp2  = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
+pp3  = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
+pp4  = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
+qq1  =  3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
+qq2  =  6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
+qq3  =  5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
+qq4  =  1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
+qq5  = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
+/*
+ * Coefficients for approximation to  erf  in [0.84375,1.25]
+ */
+pa0  = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
+pa1  =  4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
+pa2  = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
+pa3  =  3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
+pa4  = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
+pa5  =  3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
+pa6  = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
+qa1  =  1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
+qa2  =  5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
+qa3  =  7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
+qa4  =  1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
+qa5  =  1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
+qa6  =  1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
+/*
+ * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ */
+ra0  = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
+ra1  = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
+ra2  = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
+ra3  = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
+ra4  = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
+ra5  = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
+ra6  = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
+ra7  = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
+sa1  =  1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
+sa2  =  1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
+sa3  =  4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
+sa4  =  6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
+sa5  =  4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
+sa6  =  1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
+sa7  =  6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
+sa8  = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
+/*
+ * Coefficients for approximation to  erfc in [1/.35,28]
+ */
+rb0  = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
+rb1  = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
+rb2  = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
+rb3  = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
+rb4  = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
+rb5  = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
+rb6  = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
+sb1  =  3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
+sb2  =  3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
+sb3  =  1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
+sb4  =  3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
+sb5  =  2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
+sb6  =  4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
+sb7  = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
+
+double
+erf(double x)
+{
+        int32_t hx,ix,i;
+        double R,S,P,Q,s,y,z,r;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7ff00000) {            /* erf(nan)=nan */
+            i = ((uint32_t)hx>>31)<<1;
+            return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */
+        }
+
+        if(ix < 0x3feb0000) {           /* |x|<0.84375 */
+            if(ix < 0x3e300000) {       /* |x|<2**-28 */
+                if (ix < 0x00800000)
+                    return 0.125*(8.0*x+efx8*x);  /*avoid underflow */
+                return x + efx*x;
+            }
+            z = x*x;
+            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+            y = r/s;
+            return x + x*y;
+        }
+        if(ix < 0x3ff40000) {           /* 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(hx>=0) return erx + P/Q; else return -erx - P/Q;
+        }
+        if (ix >= 0x40180000) {         /* inf>|x|>=6 */
+            if(hx>=0) return one-tiny; else return tiny-one;
+        }
+        x = fabs(x);
+        s = one/(x*x);
+        if(ix< 0x4006DB6E) {    /* |x| < 1/0.35 */
+            R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+                                ra5+s*(ra6+s*ra7))))));
+            S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
+        } else {        /* |x| >= 1/0.35 */
+            R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+                                rb5+s*rb6)))));
+            S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+                                sb5+s*(sb6+s*sb7))))));
+        }
+        z  = x;
+        SET_LOW_WORD(z,0);
+        r  =  exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S);
+        if(hx>=0) return one-r/x; else return  r/x-one;
+}
+
+double
+erfc(double x)
+{
+        int32_t hx,ix;
+        double R,S,P,Q,s,y,z,r;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7ff00000) {                    /* erfc(nan)=nan */
+                                                /* erfc(+-inf)=0,2 */
+            return (double)(((uint32_t)hx>>31)<<1)+one/x;
+        }
+
+        if(ix < 0x3feb0000) {           /* |x|<0.84375 */
+            if(ix < 0x3c700000)         /* |x|<2**-56 */
+                return one-x;
+            z = x*x;
+            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+            y = r/s;
+            if(hx < 0x3fd00000) {       /* x<1/4 */
+                return one-(x+x*y);
+            } else {
+                r = x*y;
+                r += (x-half);
+                return half - r ;
+            }
+        }
+        if(ix < 0x3ff40000) {           /* 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(hx>=0) {
+                z  = one-erx; return z - P/Q;
+            } else {
+                z = erx+P/Q; return one+z;
+            }
+        }
+        if (ix < 0x403c0000) {          /* |x|<28 */
+            x = fabs(x);
+            s = one/(x*x);
+            if(ix< 0x4006DB6D) {        /* |x| < 1/.35 ~ 2.857143*/
+                R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+                                ra5+s*(ra6+s*ra7))))));
+                S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
+            } else {                    /* |x| >= 1/.35 ~ 2.857143 */
+                if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
+                R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+                                rb5+s*rb6)))));
+                S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+                                sb5+s*(sb6+s*sb7))))));
+            }
+            z  = x;
+            SET_LOW_WORD(z,0);
+            r  =  exp(-z*z-0.5625)*
+                        exp((z-x)*(z+x)+R/S);
+            if(hx>0) return r/x; else return two-r/x;
+        } else {
+            if(hx>0) return tiny*tiny; else return two-tiny;
+        }
+}
diff --git a/src/math/s_erff.c b/src/math/s_erff.c
new file mode 100644 (file)
index 0000000..28e2f7b
--- /dev/null
@@ -0,0 +1,207 @@
+/* s_erff.c -- float version of s_erf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+tiny        = 1e-30,
+half=  5.0000000000e-01, /* 0x3F000000 */
+one =  1.0000000000e+00, /* 0x3F800000 */
+two =  2.0000000000e+00, /* 0x40000000 */
+        /* c = (subfloat)0.84506291151 */
+erx =  8.4506291151e-01, /* 0x3f58560b */
+/*
+ * Coefficients for approximation to  erf on [0,0.84375]
+ */
+efx =  1.2837916613e-01, /* 0x3e0375d4 */
+efx8=  1.0270333290e+00, /* 0x3f8375d4 */
+pp0  =  1.2837916613e-01, /* 0x3e0375d4 */
+pp1  = -3.2504209876e-01, /* 0xbea66beb */
+pp2  = -2.8481749818e-02, /* 0xbce9528f */
+pp3  = -5.7702702470e-03, /* 0xbbbd1489 */
+pp4  = -2.3763017452e-05, /* 0xb7c756b1 */
+qq1  =  3.9791721106e-01, /* 0x3ecbbbce */
+qq2  =  6.5022252500e-02, /* 0x3d852a63 */
+qq3  =  5.0813062117e-03, /* 0x3ba68116 */
+qq4  =  1.3249473704e-04, /* 0x390aee49 */
+qq5  = -3.9602282413e-06, /* 0xb684e21a */
+/*
+ * Coefficients for approximation to  erf  in [0.84375,1.25]
+ */
+pa0  = -2.3621185683e-03, /* 0xbb1acdc6 */
+pa1  =  4.1485610604e-01, /* 0x3ed46805 */
+pa2  = -3.7220788002e-01, /* 0xbebe9208 */
+pa3  =  3.1834661961e-01, /* 0x3ea2fe54 */
+pa4  = -1.1089469492e-01, /* 0xbde31cc2 */
+pa5  =  3.5478305072e-02, /* 0x3d1151b3 */
+pa6  = -2.1663755178e-03, /* 0xbb0df9c0 */
+qa1  =  1.0642088205e-01, /* 0x3dd9f331 */
+qa2  =  5.4039794207e-01, /* 0x3f0a5785 */
+qa3  =  7.1828655899e-02, /* 0x3d931ae7 */
+qa4  =  1.2617121637e-01, /* 0x3e013307 */
+qa5  =  1.3637083583e-02, /* 0x3c5f6e13 */
+qa6  =  1.1984500103e-02, /* 0x3c445aa3 */
+/*
+ * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ */
+ra0  = -9.8649440333e-03, /* 0xbc21a093 */
+ra1  = -6.9385856390e-01, /* 0xbf31a0b7 */
+ra2  = -1.0558626175e+01, /* 0xc128f022 */
+ra3  = -6.2375331879e+01, /* 0xc2798057 */
+ra4  = -1.6239666748e+02, /* 0xc322658c */
+ra5  = -1.8460508728e+02, /* 0xc3389ae7 */
+ra6  = -8.1287437439e+01, /* 0xc2a2932b */
+ra7  = -9.8143291473e+00, /* 0xc11d077e */
+sa1  =  1.9651271820e+01, /* 0x419d35ce */
+sa2  =  1.3765776062e+02, /* 0x4309a863 */
+sa3  =  4.3456588745e+02, /* 0x43d9486f */
+sa4  =  6.4538726807e+02, /* 0x442158c9 */
+sa5  =  4.2900814819e+02, /* 0x43d6810b */
+sa6  =  1.0863500214e+02, /* 0x42d9451f */
+sa7  =  6.5702495575e+00, /* 0x40d23f7c */
+sa8  = -6.0424413532e-02, /* 0xbd777f97 */
+/*
+ * Coefficients for approximation to  erfc in [1/.35,28]
+ */
+rb0  = -9.8649431020e-03, /* 0xbc21a092 */
+rb1  = -7.9928326607e-01, /* 0xbf4c9dd4 */
+rb2  = -1.7757955551e+01, /* 0xc18e104b */
+rb3  = -1.6063638306e+02, /* 0xc320a2ea */
+rb4  = -6.3756646729e+02, /* 0xc41f6441 */
+rb5  = -1.0250950928e+03, /* 0xc480230b */
+rb6  = -4.8351919556e+02, /* 0xc3f1c275 */
+sb1  =  3.0338060379e+01, /* 0x41f2b459 */
+sb2  =  3.2579251099e+02, /* 0x43a2e571 */
+sb3  =  1.5367296143e+03, /* 0x44c01759 */
+sb4  =  3.1998581543e+03, /* 0x4547fdbb */
+sb5  =  2.5530502930e+03, /* 0x451f90ce */
+sb6  =  4.7452853394e+02, /* 0x43ed43a7 */
+sb7  = -2.2440952301e+01; /* 0xc1b38712 */
+
+float
+erff(float x)
+{
+        int32_t hx,ix,i;
+        float R,S,P,Q,s,y,z,r;
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7f800000) {            /* erf(nan)=nan */
+            i = ((uint32_t)hx>>31)<<1;
+            return (float)(1-i)+one/x;  /* erf(+-inf)=+-1 */
+        }
+
+        if(ix < 0x3f580000) {           /* |x|<0.84375 */
+            if(ix < 0x31800000) {       /* |x|<2**-28 */
+                if (ix < 0x04000000)
+                    /*avoid underflow */
+                    return (float)0.125*((float)8.0*x+efx8*x);
+                return x + efx*x;
+            }
+            z = x*x;
+            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+            y = r/s;
+            return x + x*y;
+        }
+        if(ix < 0x3fa00000) {           /* 0.84375 <= |x| < 1.25 */
+            s = fabsf(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(hx>=0) return erx + P/Q; else return -erx - P/Q;
+        }
+        if (ix >= 0x40c00000) {         /* inf>|x|>=6 */
+            if(hx>=0) return one-tiny; else return tiny-one;
+        }
+        x = fabsf(x);
+        s = one/(x*x);
+        if(ix< 0x4036DB6E) {    /* |x| < 1/0.35 */
+            R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+                                ra5+s*(ra6+s*ra7))))));
+            S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
+        } else {        /* |x| >= 1/0.35 */
+            R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+                                rb5+s*rb6)))));
+            S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+                                sb5+s*(sb6+s*sb7))))));
+        }
+        GET_FLOAT_WORD(ix,x);
+        SET_FLOAT_WORD(z,ix&0xfffff000);
+        r  =  expf(-z*z-(float)0.5625)*expf((z-x)*(z+x)+R/S);
+        if(hx>=0) return one-r/x; else return  r/x-one;
+}
+
+float
+erfcf(float x)
+{
+        int32_t hx,ix;
+        float R,S,P,Q,s,y,z,r;
+        GET_FLOAT_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7f800000) {                    /* erfc(nan)=nan */
+                                                /* erfc(+-inf)=0,2 */
+            return (float)(((uint32_t)hx>>31)<<1)+one/x;
+        }
+
+        if(ix < 0x3f580000) {           /* |x|<0.84375 */
+            if(ix < 0x23800000)         /* |x|<2**-56 */
+                return one-x;
+            z = x*x;
+            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+            y = r/s;
+            if(hx < 0x3e800000) {       /* x<1/4 */
+                return one-(x+x*y);
+            } else {
+                r = x*y;
+                r += (x-half);
+                return half - r ;
+            }
+        }
+        if(ix < 0x3fa00000) {           /* 0.84375 <= |x| < 1.25 */
+            s = fabsf(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(hx>=0) {
+                z  = one-erx; return z - P/Q;
+            } else {
+                z = erx+P/Q; return one+z;
+            }
+        }
+        if (ix < 0x41e00000) {          /* |x|<28 */
+            x = fabsf(x);
+            s = one/(x*x);
+            if(ix< 0x4036DB6D) {        /* |x| < 1/.35 ~ 2.857143*/
+                R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+                                ra5+s*(ra6+s*ra7))))));
+                S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
+            } else {                    /* |x| >= 1/.35 ~ 2.857143 */
+                if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */
+                R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+                                rb5+s*rb6)))));
+                S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+                                sb5+s*(sb6+s*sb7))))));
+            }
+            GET_FLOAT_WORD(ix,x);
+            SET_FLOAT_WORD(z,ix&0xfffff000);
+            r  =  expf(-z*z-(float)0.5625)*
+                        expf((z-x)*(z+x)+R/S);
+            if(hx>0) return r/x; else return two-r/x;
+        } else {
+            if(hx>0) return tiny*tiny; else return two-tiny;
+        }
+}
diff --git a/src/math/s_expm1.c b/src/math/s_expm1.c
new file mode 100644 (file)
index 0000000..6f1f667
--- /dev/null
@@ -0,0 +1,217 @@
+/* @(#)s_expm1.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* expm1(x)
+ * Returns exp(x)-1, the exponential of x minus 1.
+ *
+ * Method
+ *   1. Argument reduction:
+ *      Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2 ~ 0.34658
+ *
+ *      Here a correction term c will be computed to compensate
+ *      the error in r when rounded to a floating-point number.
+ *
+ *   2. Approximating expm1(r) by a special rational function on
+ *      the interval [0,0.34658]:
+ *      Since
+ *          r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
+ *      we define R1(r*r) by
+ *          r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
+ *      That is,
+ *          R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+ *                   = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+ *                   = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+ *      We use a special Reme algorithm on [0,0.347] to generate
+ *      a polynomial of degree 5 in r*r to approximate R1. The
+ *      maximum error of this polynomial approximation is bounded
+ *      by 2**-61. In other words,
+ *          R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+ *      where   Q1  =  -1.6666666666666567384E-2,
+ *              Q2  =   3.9682539681370365873E-4,
+ *              Q3  =  -9.9206344733435987357E-6,
+ *              Q4  =   2.5051361420808517002E-7,
+ *              Q5  =  -6.2843505682382617102E-9;
+ *      (where z=r*r, and the values of Q1 to Q5 are listed below)
+ *      with error bounded by
+ *          |                  5           |     -61
+ *          | 1.0+Q1*z+...+Q5*z   -  R1(z) | <= 2
+ *          |                              |
+ *
+ *      expm1(r) = exp(r)-1 is then computed by the following
+ *      specific way which minimize the accumulation rounding error:
+ *                             2     3
+ *                            r     r    [ 3 - (R1 + R1*r/2)  ]
+ *            expm1(r) = r + --- + --- * [--------------------]
+ *                            2     2    [ 6 - r*(3 - R1*r/2) ]
+ *
+ *      To compensate the error in the argument reduction, we use
+ *              expm1(r+c) = expm1(r) + c + expm1(r)*c
+ *                         ~ expm1(r) + c + r*c
+ *      Thus c+r*c will be added in as the correction terms for
+ *      expm1(r+c). Now rearrange the term to avoid optimization
+ *      screw up:
+ *                      (      2                                    2 )
+ *                      ({  ( r    [ R1 -  (3 - R1*r/2) ]  )  }    r  )
+ *       expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+ *                      ({  ( 2    [ 6 - r*(3 - R1*r/2) ]  )  }    2  )
+ *                      (                                             )
+ *
+ *                 = r - E
+ *   3. Scale back to obtain expm1(x):
+ *      From step 1, we have
+ *         expm1(x) = either 2^k*[expm1(r)+1] - 1
+ *                  = or     2^k*[expm1(r) + (1-2^-k)]
+ *   4. Implementation notes:
+ *      (A). To save one multiplication, we scale the coefficient Qi
+ *           to Qi*2^i, and replace z by (x^2)/2.
+ *      (B). To achieve maximum accuracy, we compute expm1(x) by
+ *        (i)   if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+ *        (ii)  if k=0, return r-E
+ *        (iii) if k=-1, return 0.5*(r-E)-0.5
+ *        (iv)  if k=1 if r < -0.25, return 2*((r+0.5)- E)
+ *                     else          return  1.0+2.0*(r-E);
+ *        (v)   if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+ *        (vi)  if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+ *        (vii) return 2^k(1-((E+2^-k)-r))
+ *
+ * Special cases:
+ *      expm1(INF) is INF, expm1(NaN) is NaN;
+ *      expm1(-INF) is -1, and
+ *      for finite argument, only expm1(0)=0 is exact.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *      For IEEE double
+ *          if x >  7.09782712893383973096e+02 then expm1(x) overflow
+ *
+ * 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 <math.h>
+#include "math_private.h"
+
+static const double
+one             = 1.0,
+huge            = 1.0e+300,
+tiny            = 1.0e-300,
+o_threshold     = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */
+ln2_hi          = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */
+ln2_lo          = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */
+invln2          = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */
+        /* scaled coefficients related to expm1 */
+Q1  =  -3.33333333333331316428e-02, /* BFA11111 111110F4 */
+Q2  =   1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */
+Q3  =  -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
+Q4  =   4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
+Q5  =  -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
+
+double
+expm1(double x)
+{
+        double y,hi,lo,c=0.0,t,e,hxs,hfx,r1;
+        int32_t k,xsb;
+        uint32_t hx;
+
+        GET_HIGH_WORD(hx,x);
+        xsb = hx&0x80000000;            /* sign bit of x */
+        if(xsb==0) y=x; else y= -x;     /* y = |x| */
+        hx &= 0x7fffffff;               /* high word of |x| */
+
+    /* filter out huge and non-finite argument */
+        if(hx >= 0x4043687A) {                  /* if |x|>=56*ln2 */
+            if(hx >= 0x40862E42) {              /* if |x|>=709.78... */
+                if(hx>=0x7ff00000) {
+                    uint32_t low;
+                    GET_LOW_WORD(low,x);
+                    if(((hx&0xfffff)|low)!=0)
+                         return x+x;     /* NaN */
+                    else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+                }
+                if(x > o_threshold) return huge*huge; /* overflow */
+            }
+            if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */
+                if(x+tiny<0.0)          /* raise inexact */
+                return tiny-one;        /* return -1 */
+            }
+        }
+
+    /* argument reduction */
+        if(hx > 0x3fd62e42) {           /* if  |x| > 0.5 ln2 */
+            if(hx < 0x3FF0A2B2) {       /* and |x| < 1.5 ln2 */
+                if(xsb==0)
+                    {hi = x - ln2_hi; lo =  ln2_lo;  k =  1;}
+                else
+                    {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}
+            } else {
+                k  = invln2*x+((xsb==0)?0.5:-0.5);
+                t  = k;
+                hi = x - t*ln2_hi;      /* t*ln2_hi is exact here */
+                lo = t*ln2_lo;
+            }
+            x  = hi - lo;
+            c  = (hi-x)-lo;
+        }
+        else if(hx < 0x3c900000) {      /* when |x|<2**-54, return x */
+            t = huge+x; /* return x with inexact flags when x!=0 */
+            return x - (t-(huge+x));
+        }
+        else k = 0;
+
+    /* x is now in primary range */
+        hfx = 0.5*x;
+        hxs = x*hfx;
+        r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+        t  = 3.0-r1*hfx;
+        e  = hxs*((r1-t)/(6.0 - x*t));
+        if(k==0) return x - (x*e-hxs);          /* c is 0 */
+        else {
+            e  = (x*(e-c)-c);
+            e -= hxs;
+            if(k== -1) return 0.5*(x-e)-0.5;
+            if(k==1) {
+                if(x < -0.25) return -2.0*(e-(x+0.5));
+                else          return  one+2.0*(x-e);
+            }
+            if (k <= -2 || k>56) {   /* suffice to return exp(x)-1 */
+                uint32_t high;
+                y = one-(e-x);
+                GET_HIGH_WORD(high,y);
+                SET_HIGH_WORD(y,high+(k<<20));  /* add k to y's exponent */
+                return y-one;
+            }
+            t = one;
+            if(k<20) {
+                uint32_t high;
+                SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k));  /* t=1-2^-k */
+                y = t-(e-x);
+                GET_HIGH_WORD(high,y);
+                SET_HIGH_WORD(y,high+(k<<20));  /* add k to y's exponent */
+           } else {
+                uint32_t high;
+                SET_HIGH_WORD(t,((0x3ff-k)<<20));       /* 2^-k */
+                y = x-(e+t);
+                y += one;
+                GET_HIGH_WORD(high,y);
+                SET_HIGH_WORD(y,high+(k<<20));  /* add k to y's exponent */
+            }
+        }
+        return y;
+}
diff --git a/src/math/s_expm1f.c b/src/math/s_expm1f.c
new file mode 100644 (file)
index 0000000..b22cf0f
--- /dev/null
@@ -0,0 +1,122 @@
+/* s_expm1f.c -- float version of s_expm1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+one             = 1.0,
+huge            = 1.0e+30,
+tiny            = 1.0e-30,
+o_threshold     = 8.8721679688e+01,/* 0x42b17180 */
+ln2_hi          = 6.9313812256e-01,/* 0x3f317180 */
+ln2_lo          = 9.0580006145e-06,/* 0x3717f7d1 */
+invln2          = 1.4426950216e+00,/* 0x3fb8aa3b */
+        /* scaled coefficients related to expm1 */
+Q1  =  -3.3333335072e-02, /* 0xbd088889 */
+Q2  =   1.5873016091e-03, /* 0x3ad00d01 */
+Q3  =  -7.9365076090e-05, /* 0xb8a670cd */
+Q4  =   4.0082177293e-06, /* 0x36867e54 */
+Q5  =  -2.0109921195e-07; /* 0xb457edbb */
+
+float
+expm1f(float x)
+{
+        float y,hi,lo,c=0.0,t,e,hxs,hfx,r1;
+        int32_t k,xsb;
+        uint32_t hx;
+
+        GET_FLOAT_WORD(hx,x);
+        xsb = hx&0x80000000;            /* sign bit of x */
+        if(xsb==0) y=x; else y= -x;     /* y = |x| */
+        hx &= 0x7fffffff;               /* high word of |x| */
+
+    /* filter out huge and non-finite argument */
+        if(hx >= 0x4195b844) {                  /* if |x|>=27*ln2 */
+            if(hx >= 0x42b17218) {              /* if |x|>=88.721... */
+                if(hx>0x7f800000)
+                    return x+x;          /* NaN */
+                if(hx==0x7f800000)
+                    return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+                if(x > o_threshold) return huge*huge; /* overflow */
+            }
+            if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
+                if(x+tiny<(float)0.0)   /* raise inexact */
+                return tiny-one;        /* return -1 */
+            }
+        }
+
+    /* argument reduction */
+        if(hx > 0x3eb17218) {           /* if  |x| > 0.5 ln2 */
+            if(hx < 0x3F851592) {       /* and |x| < 1.5 ln2 */
+                if(xsb==0)
+                    {hi = x - ln2_hi; lo =  ln2_lo;  k =  1;}
+                else
+                    {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}
+            } else {
+                k  = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
+                t  = k;
+                hi = x - t*ln2_hi;      /* t*ln2_hi is exact here */
+                lo = t*ln2_lo;
+            }
+            x  = hi - lo;
+            c  = (hi-x)-lo;
+        }
+        else if(hx < 0x33000000) {      /* when |x|<2**-25, return x */
+            t = huge+x; /* return x with inexact flags when x!=0 */
+            return x - (t-(huge+x));
+        }
+        else k = 0;
+
+    /* x is now in primary range */
+        hfx = (float)0.5*x;
+        hxs = x*hfx;
+        r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+        t  = (float)3.0-r1*hfx;
+        e  = hxs*((r1-t)/((float)6.0 - x*t));
+        if(k==0) return x - (x*e-hxs);          /* c is 0 */
+        else {
+            e  = (x*(e-c)-c);
+            e -= hxs;
+            if(k== -1) return (float)0.5*(x-e)-(float)0.5;
+            if(k==1) {
+                if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
+                else          return  one+(float)2.0*(x-e);
+            }
+            if (k <= -2 || k>56) {   /* suffice to return exp(x)-1 */
+                int32_t i;
+                y = one-(e-x);
+                GET_FLOAT_WORD(i,y);
+                SET_FLOAT_WORD(y,i+(k<<23));    /* add k to y's exponent */
+                return y-one;
+            }
+            t = one;
+            if(k<23) {
+                int32_t i;
+                SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
+                y = t-(e-x);
+                GET_FLOAT_WORD(i,y);
+                SET_FLOAT_WORD(y,i+(k<<23));    /* add k to y's exponent */
+           } else {
+                int32_t i;
+                SET_FLOAT_WORD(t,((0x7f-k)<<23));       /* 2^-k */
+                y = x-(e+t);
+                y += one;
+                GET_FLOAT_WORD(i,y);
+                SET_FLOAT_WORD(y,i+(k<<23));    /* add k to y's exponent */
+            }
+        }
+        return y;
+}
diff --git a/src/math/s_fabs.c b/src/math/s_fabs.c
new file mode 100644 (file)
index 0000000..7443325
--- /dev/null
@@ -0,0 +1,27 @@
+/* @(#)s_fabs.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+fabs(double x)
+{
+        uint32_t high;
+        GET_HIGH_WORD(high,x);
+        SET_HIGH_WORD(x,high&0x7fffffff);
+        return x;
+}
diff --git a/src/math/s_fabsf.c b/src/math/s_fabsf.c
new file mode 100644 (file)
index 0000000..655d57d
--- /dev/null
@@ -0,0 +1,30 @@
+/* s_fabsf.c -- float version of s_fabs.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * fabsf(x) returns the absolute value of x.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+fabsf(float x)
+{
+        uint32_t ix;
+        GET_FLOAT_WORD(ix,x);
+        SET_FLOAT_WORD(x,ix&0x7fffffff);
+        return x;
+}
diff --git a/src/math/s_floor.c b/src/math/s_floor.c
new file mode 100644 (file)
index 0000000..273cf6f
--- /dev/null
@@ -0,0 +1,69 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *      Bit twiddling.
+ * Exception:
+ *      Inexact flag raised if x not equal to floor(x).
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double
+floor(double x)
+{
+        int32_t i0,i1,j0;
+        uint32_t i,j;
+        EXTRACT_WORDS(i0,i1,x);
+        j0 = ((i0>>20)&0x7ff)-0x3ff;
+        if(j0<20) {
+            if(j0<0) {  /* raise inexact if x != 0 */
+                if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+                    if(i0>=0) {i0=i1=0;}
+                    else if(((i0&0x7fffffff)|i1)!=0)
+                        { i0=0xbff00000;i1=0;}
+                }
+            } else {
+                i = (0x000fffff)>>j0;
+                if(((i0&i)|i1)==0) return x; /* x is integral */
+                if(huge+x>0.0) {        /* raise inexact flag */
+                    if(i0<0) i0 += (0x00100000)>>j0;
+                    i0 &= (~i); i1=0;
+                }
+            }
+        } else if (j0>51) {
+            if(j0==0x400) return x+x;   /* inf or NaN */
+            else return x;              /* x is integral */
+        } else {
+            i = ((uint32_t)(0xffffffff))>>(j0-20);
+            if((i1&i)==0) return x;     /* x is integral */
+            if(huge+x>0.0) {            /* raise inexact flag */
+                if(i0<0) {
+                    if(j0==20) i0+=1;
+                    else {
+                        j = i1+(1<<(52-j0));
+                        if(j<i1) i0 +=1 ;       /* got a carry */
+                        i1=j;
+                    }
+                }
+                i1 &= (~i);
+            }
+        }
+        INSERT_WORDS(x,i0,i1);
+        return x;
+}
diff --git a/src/math/s_floorf.c b/src/math/s_floorf.c
new file mode 100644 (file)
index 0000000..1164dec
--- /dev/null
@@ -0,0 +1,58 @@
+/* s_floorf.c -- float version of s_floor.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * floorf(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *      Bit twiddling.
+ * Exception:
+ *      Inexact flag raised if x not equal to floorf(x).
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float huge = 1.0e30;
+
+float
+floorf(float x)
+{
+        int32_t i0,j0;
+        uint32_t i;
+        GET_FLOAT_WORD(i0,x);
+        j0 = ((i0>>23)&0xff)-0x7f;
+        if(j0<23) {
+            if(j0<0) {  /* raise inexact if x != 0 */
+                if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+                    if(i0>=0) {i0=0;}
+                    else if((i0&0x7fffffff)!=0)
+                        { i0=0xbf800000;}
+                }
+            } else {
+                i = (0x007fffff)>>j0;
+                if((i0&i)==0) return x; /* x is integral */
+                if(huge+x>(float)0.0) { /* raise inexact flag */
+                    if(i0<0) i0 += (0x00800000)>>j0;
+                    i0 &= (~i);
+                }
+            }
+        } else {
+            if(j0==0x80) return x+x;    /* inf or NaN */
+            else return x;              /* x is integral */
+        }
+        SET_FLOAT_WORD(x,i0);
+        return x;
+}
diff --git a/src/math/s_ilogb.c b/src/math/s_ilogb.c
new file mode 100644 (file)
index 0000000..f1ac498
--- /dev/null
@@ -0,0 +1,45 @@
+/* @(#)s_ilogb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* ilogb(double x)
+ * return the binary exponent of non-zero x
+ * ilogb(0) = FP_ILOGB0
+ * ilogb(NaN) = FP_ILOGBNAN (no signal is raised)
+ * ilogb(inf) = INT_MAX (no signal is raised)
+ */
+
+#include <limits.h>
+
+#include <math.h>
+#include "math_private.h"
+
+int ilogb(double x)
+{
+        int32_t hx,lx,ix;
+
+        EXTRACT_WORDS(hx,lx,x);
+        hx &= 0x7fffffff;
+        if(hx<0x00100000) {
+            if((hx|lx)==0)
+                return FP_ILOGB0;
+            else                        /* subnormal x */
+                if(hx==0) {
+                    for (ix = -1043; lx>0; lx<<=1) ix -=1;
+                } else {
+                    for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
+                }
+            return ix;
+        }
+        else if (hx<0x7ff00000) return (hx>>20)-1023;
+        else if (hx>0x7ff00000 || lx!=0) return FP_ILOGBNAN;
+        else return INT_MAX;
+}
diff --git a/src/math/s_ilogbf.c b/src/math/s_ilogbf.c
new file mode 100644 (file)
index 0000000..30359fe
--- /dev/null
@@ -0,0 +1,37 @@
+/* s_ilogbf.c -- float version of s_ilogb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <limits.h>
+
+#include <math.h>
+#include "math_private.h"
+
+int ilogbf(float x)
+{
+        int32_t hx,ix;
+
+        GET_FLOAT_WORD(hx,x);
+        hx &= 0x7fffffff;
+        if(hx<0x00800000) {
+            if(hx==0)
+                return FP_ILOGB0;
+            else                        /* subnormal x */
+                for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
+            return ix;
+        }
+        else if (hx<0x7f800000) return (hx>>23)-127;
+        else if (hx>0x7f800000) return FP_ILOGBNAN;
+        else return INT_MAX;
+}
diff --git a/src/math/s_ldexp.c b/src/math/s_ldexp.c
new file mode 100644 (file)
index 0000000..f4d1cd6
--- /dev/null
@@ -0,0 +1,6 @@
+#include <math.h>
+
+double ldexp(double x, int n)
+{
+       return scalbn(x, n);
+}
diff --git a/src/math/s_ldexpf.c b/src/math/s_ldexpf.c
new file mode 100644 (file)
index 0000000..3bad5f3
--- /dev/null
@@ -0,0 +1,6 @@
+#include <math.h>
+
+float ldexpf(float x, int n)
+{
+       return scalbnf(x, n);
+}
diff --git a/src/math/s_llrint.c b/src/math/s_llrint.c
new file mode 100644 (file)
index 0000000..2b1e00d
--- /dev/null
@@ -0,0 +1,8 @@
+#include <math.h>
+
+// FIXME: incorrect exception behavior
+
+long long llrint(double x)
+{
+       return rint(x);
+}
diff --git a/src/math/s_log1p.c b/src/math/s_log1p.c
new file mode 100644 (file)
index 0000000..886d5ab
--- /dev/null
@@ -0,0 +1,157 @@
+/* @(#)s_log1p.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* double log1p(double x)
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *                      1+x = 2^k * (1+f),
+ *         where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *      Note. If k=0, then f=x is exact. However, if k!=0, then f
+ *      may not be representable exactly. In that case, a correction
+ *      term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+ *      log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+ *      and add back the correction term c/u.
+ *      (Note: when x > 2**53, one can simply return log(x))
+ *
+ *   2. Approximation of log1p(f).
+ *      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 + .....,
+ *               = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ *      a polynomial of degree 14 to approximate R The maximum error
+ *      of this polynomial approximation is bounded by 2**-58.45. In
+ *      other words,
+ *                      2      4      6      8      10      12      14
+ *          R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
+ *      (the values of Lp1 to Lp7 are listed in the program)
+ *      and
+ *          |      2          14          |     -58.45
+ *          | Lp1*s +...+Lp7*s    -  R(z) | <= 2
+ *          |                             |
+ *      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *      In order to guarantee error in log below 1ulp, we compute log
+ *      by
+ *              log1p(f) = f - (hfsq - s*(hfsq+R)).
+ *
+ *      3. Finally, log1p(x) = k*ln2 + log1p(f).
+ *                           = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *         Here ln2 is split into two floating point number:
+ *                      ln2_hi + ln2_lo,
+ *         where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *      log1p(x) is NaN with signal if x < -1 (including -INF) ;
+ *      log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+ *      log1p(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit 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.
+ *
+ * Note: Assuming log() return accurate answer, the following
+ *       algorithm can be used to compute log1p(x) to within a few ULP:
+ *
+ *              u = 1+x;
+ *              if(u==1.0) return x ; else
+ *                         return log(u)*(x/(u-1.0));
+ *
+ *       See HP-15C Advanced Functions Handbook, p.193.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+ln2_hi  =  6.93147180369123816490e-01,  /* 3fe62e42 fee00000 */
+ln2_lo  =  1.90821492927058770002e-10,  /* 3dea39ef 35793c76 */
+two54   =  1.80143985094819840000e+16,  /* 43500000 00000000 */
+Lp1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
+Lp2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
+Lp3 = 2.857142874366239149e-01,  /* 3FD24924 94229359 */
+Lp4 = 2.222219843214978396e-01,  /* 3FCC71C5 1D8E78AF */
+Lp5 = 1.818357216161805012e-01,  /* 3FC74664 96CB03DE */
+Lp6 = 1.531383769920937332e-01,  /* 3FC39A09 D078C69F */
+Lp7 = 1.479819860511658591e-01;  /* 3FC2F112 DF3E5244 */
+
+static const double zero = 0.0;
+
+double
+log1p(double x)
+{
+        double hfsq,f=0,c=0,s,z,R,u;
+        int32_t k,hx,hu=0,ax;
+
+        GET_HIGH_WORD(hx,x);
+        ax = hx&0x7fffffff;
+
+        k = 1;
+        if (hx < 0x3FDA827A) {                  /* x < 0.41422  */
+            if(ax>=0x3ff00000) {                /* x <= -1.0 */
+                if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */
+                else return (x-x)/(x-x);        /* log1p(x<-1)=NaN */
+            }
+            if(ax<0x3e200000) {                 /* |x| < 2**-29 */
+                if(two54+x>zero                 /* raise inexact */
+                    &&ax<0x3c900000)            /* |x| < 2**-54 */
+                    return x;
+                else
+                    return x - x*x*0.5;
+            }
+            if(hx>0||hx<=((int32_t)0xbfd2bec3)) {
+                k=0;f=x;hu=1;}  /* -0.2929<x<0.41422 */
+        }
+        if (hx >= 0x7ff00000) return x+x;
+        if(k!=0) {
+            if(hx<0x43400000) {
+                u  = 1.0+x;
+                GET_HIGH_WORD(hu,u);
+                k  = (hu>>20)-1023;
+                c  = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */
+                c /= u;
+            } else {
+                u  = x;
+                GET_HIGH_WORD(hu,u);
+                k  = (hu>>20)-1023;
+                c  = 0;
+            }
+            hu &= 0x000fffff;
+            if(hu<0x6a09e) {
+                SET_HIGH_WORD(u,hu|0x3ff00000); /* normalize u */
+            } else {
+                k += 1;
+                SET_HIGH_WORD(u,hu|0x3fe00000); /* normalize u/2 */
+                hu = (0x00100000-hu)>>2;
+            }
+            f = u-1.0;
+        }
+        hfsq=0.5*f*f;
+        if(hu==0) {     /* |f| < 2**-20 */
+            if(f==zero) { if(k==0) return zero;
+                          else {c += k*ln2_lo; return k*ln2_hi+c;} }
+            R = hfsq*(1.0-0.66666666666666666*f);
+            if(k==0) return f-R; else
+                     return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+        }
+        s = f/(2.0+f);
+        z = s*s;
+        R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+        if(k==0) return f-(hfsq-s*(hfsq+R)); else
+                 return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
diff --git a/src/math/s_log1pf.c b/src/math/s_log1pf.c
new file mode 100644 (file)
index 0000000..dcdd6bb
--- /dev/null
@@ -0,0 +1,96 @@
+/* s_log1pf.c -- float version of s_log1p.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+ln2_hi =   6.9313812256e-01,    /* 0x3f317180 */
+ln2_lo =   9.0580006145e-06,    /* 0x3717f7d1 */
+two25 =    3.355443200e+07,     /* 0x4c000000 */
+Lp1 = 6.6666668653e-01, /* 3F2AAAAB */
+Lp2 = 4.0000000596e-01, /* 3ECCCCCD */
+Lp3 = 2.8571429849e-01, /* 3E924925 */
+Lp4 = 2.2222198546e-01, /* 3E638E29 */
+Lp5 = 1.8183572590e-01, /* 3E3A3325 */
+Lp6 = 1.5313838422e-01, /* 3E1CD04F */
+Lp7 = 1.4798198640e-01; /* 3E178897 */
+
+static const float zero = 0.0;
+
+float
+log1pf(float x)
+{
+        float hfsq,f=0,c=0,s,z,R,u;
+        int32_t k,hx,hu=0,ax;
+
+        GET_FLOAT_WORD(hx,x);
+        ax = hx&0x7fffffff;
+
+        k = 1;
+        if (hx < 0x3ed413d7) {                  /* x < 0.41422  */
+            if(ax>=0x3f800000) {                /* x <= -1.0 */
+                if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
+                else return (x-x)/(x-x);        /* log1p(x<-1)=NaN */
+            }
+            if(ax<0x31000000) {                 /* |x| < 2**-29 */
+                if(two25+x>zero                 /* raise inexact */
+                    &&ax<0x24800000)            /* |x| < 2**-54 */
+                    return x;
+                else
+                    return x - x*x*(float)0.5;
+            }
+            if(hx>0||hx<=((int32_t)0xbe95f61f)) {
+                k=0;f=x;hu=1;}  /* -0.2929<x<0.41422 */
+        }
+        if (hx >= 0x7f800000) return x+x;
+        if(k!=0) {
+            if(hx<0x5a000000) {
+                u  = (float)1.0+x;
+                GET_FLOAT_WORD(hu,u);
+                k  = (hu>>23)-127;
+                /* correction term */
+                c  = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
+                c /= u;
+            } else {
+                u  = x;
+                GET_FLOAT_WORD(hu,u);
+                k  = (hu>>23)-127;
+                c  = 0;
+            }
+            hu &= 0x007fffff;
+            if(hu<0x3504f7) {
+                SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
+            } else {
+                k += 1;
+                SET_FLOAT_WORD(u,hu|0x3f000000);        /* normalize u/2 */
+                hu = (0x00800000-hu)>>2;
+            }
+            f = u-(float)1.0;
+        }
+        hfsq=(float)0.5*f*f;
+        if(hu==0) {     /* |f| < 2**-20 */
+            if(f==zero) { if(k==0) return zero;
+                          else {c += k*ln2_lo; return k*ln2_hi+c;} }
+            R = hfsq*((float)1.0-(float)0.66666666666666666*f);
+            if(k==0) return f-R; else
+                     return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+        }
+        s = f/((float)2.0+f);
+        z = s*s;
+        R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+        if(k==0) return f-(hfsq-s*(hfsq+R)); else
+                 return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
diff --git a/src/math/s_logb.c b/src/math/s_logb.c
new file mode 100644 (file)
index 0000000..be399c7
--- /dev/null
@@ -0,0 +1,34 @@
+/* @(#)s_logb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * double logb(x)
+ * IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
+ * Use ilogb instead.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+logb(double x)
+{
+        int32_t lx,ix;
+        EXTRACT_WORDS(ix,lx,x);
+        ix &= 0x7fffffff;                       /* high |x| */
+        if((ix|lx)==0) return -1.0/fabs(x);
+        if(ix>=0x7ff00000) return x*x;
+        if((ix>>=20)==0)                        /* IEEE 754 logb */
+                return -1022.0;
+        else
+                return (double) (ix-1023);
+}
diff --git a/src/math/s_logbf.c b/src/math/s_logbf.c
new file mode 100644 (file)
index 0000000..747664d
--- /dev/null
@@ -0,0 +1,31 @@
+/* s_logbf.c -- float version of s_logb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+logbf(float x)
+{
+        int32_t ix;
+        GET_FLOAT_WORD(ix,x);
+        ix &= 0x7fffffff;                       /* high |x| */
+        if(ix==0) return (float)-1.0/fabsf(x);
+        if(ix>=0x7f800000) return x*x;
+        if((ix>>=23)==0)                        /* IEEE 754 logb */
+                return -126.0;
+        else
+                return (float) (ix-127);
+}
diff --git a/src/math/s_lrint.c b/src/math/s_lrint.c
new file mode 100644 (file)
index 0000000..da8e198
--- /dev/null
@@ -0,0 +1,8 @@
+#include <math.h>
+
+// FIXME: incorrect exception behavior
+
+long lrint(double x)
+{
+       return rint(x);
+}
diff --git a/src/math/s_lrintf.c b/src/math/s_lrintf.c
new file mode 100644 (file)
index 0000000..d0b469b
--- /dev/null
@@ -0,0 +1,8 @@
+#include <math.h>
+
+// FIXME: incorrect exception behavior
+
+long lrintf(float x)
+{
+       return rintf(x);
+}
diff --git a/src/math/s_modf.c b/src/math/s_modf.c
new file mode 100644 (file)
index 0000000..a5528d6
--- /dev/null
@@ -0,0 +1,71 @@
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modf(double x, double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ *      Bit twiddling.
+ *
+ * Exception:
+ *      No exception.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one = 1.0;
+
+double
+modf(double x, double *iptr)
+{
+        int32_t i0,i1,j0;
+        uint32_t i;
+        EXTRACT_WORDS(i0,i1,x);
+        j0 = ((i0>>20)&0x7ff)-0x3ff;    /* exponent of x */
+        if(j0<20) {                     /* integer part in high x */
+            if(j0<0) {                  /* |x|<1 */
+                INSERT_WORDS(*iptr,i0&0x80000000,0);    /* *iptr = +-0 */
+                return x;
+            } else {
+                i = (0x000fffff)>>j0;
+                if(((i0&i)|i1)==0) {            /* x is integral */
+                    uint32_t high;
+                    *iptr = x;
+                    GET_HIGH_WORD(high,x);
+                    INSERT_WORDS(x,high&0x80000000,0);  /* return +-0 */
+                    return x;
+                } else {
+                    INSERT_WORDS(*iptr,i0&(~i),0);
+                    return x - *iptr;
+                }
+            }
+        } else if (j0>51) {             /* no fraction part */
+            uint32_t high;
+            *iptr = x*one;
+            GET_HIGH_WORD(high,x);
+            INSERT_WORDS(x,high&0x80000000,0);  /* return +-0 */
+            return x;
+        } else {                        /* fraction part in low x */
+            i = ((uint32_t)(0xffffffff))>>(j0-20);
+            if((i1&i)==0) {             /* x is integral */
+                uint32_t high;
+                *iptr = x;
+                GET_HIGH_WORD(high,x);
+                INSERT_WORDS(x,high&0x80000000,0);      /* return +-0 */
+                return x;
+            } else {
+                INSERT_WORDS(*iptr,i0,i1&(~i));
+                return x - *iptr;
+            }
+        }
+}
diff --git a/src/math/s_modff.c b/src/math/s_modff.c
new file mode 100644 (file)
index 0000000..de4dfd2
--- /dev/null
@@ -0,0 +1,52 @@
+/* s_modff.c -- float version of s_modf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one = 1.0;
+
+float
+modff(float x, float *iptr)
+{
+        int32_t i0,j0;
+        uint32_t i;
+        GET_FLOAT_WORD(i0,x);
+        j0 = ((i0>>23)&0xff)-0x7f;      /* exponent of x */
+        if(j0<23) {                     /* integer part in x */
+            if(j0<0) {                  /* |x|<1 */
+                SET_FLOAT_WORD(*iptr,i0&0x80000000);    /* *iptr = +-0 */
+                return x;
+            } else {
+                i = (0x007fffff)>>j0;
+                if((i0&i)==0) {                 /* x is integral */
+                    uint32_t ix;
+                    *iptr = x;
+                    GET_FLOAT_WORD(ix,x);
+                    SET_FLOAT_WORD(x,ix&0x80000000);    /* return +-0 */
+                    return x;
+                } else {
+                    SET_FLOAT_WORD(*iptr,i0&(~i));
+                    return x - *iptr;
+                }
+            }
+        } else {                        /* no fraction part */
+            uint32_t ix;
+            *iptr = x*one;
+            GET_FLOAT_WORD(ix,x);
+            SET_FLOAT_WORD(x,ix&0x80000000);    /* return +-0 */
+            return x;
+        }
+}
diff --git a/src/math/s_nextafter.c b/src/math/s_nextafter.c
new file mode 100644 (file)
index 0000000..46d298e
--- /dev/null
@@ -0,0 +1,72 @@
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ *      nextafter(x,y)
+ *      return the next machine floating-point number of x in the
+ *      direction toward y.
+ *   Special cases:
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+nextafter(double x, double y)
+{
+        volatile double t;
+        int32_t hx,hy,ix,iy;
+        uint32_t lx,ly;
+
+        EXTRACT_WORDS(hx,lx,x);
+        EXTRACT_WORDS(hy,ly,y);
+        ix = hx&0x7fffffff;             /* |x| */
+        iy = hy&0x7fffffff;             /* |y| */
+
+        if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
+           ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))     /* y is nan */
+           return x+y;
+        if(x==y) return y;              /* x=y, return y */
+        if((ix|lx)==0) {                        /* x == 0 */
+            INSERT_WORDS(x,hy&0x80000000,1);    /* return +-minsubnormal */
+            t = x*x;
+            if(t==x) return t; else return x;   /* raise underflow flag */
+        }
+        if(hx>=0) {                             /* x > 0 */
+            if(hx>hy||((hx==hy)&&(lx>ly))) {    /* x > y, x -= ulp */
+                if(lx==0) hx -= 1;
+                lx -= 1;
+            } else {                            /* x < y, x += ulp */
+                lx += 1;
+                if(lx==0) hx += 1;
+            }
+        } else {                                /* x < 0 */
+            if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
+                if(lx==0) hx -= 1;
+                lx -= 1;
+            } else {                            /* x > y, x += ulp */
+                lx += 1;
+                if(lx==0) hx += 1;
+            }
+        }
+        hy = hx&0x7ff00000;
+        if(hy>=0x7ff00000) return x+x;  /* overflow  */
+        if(hy<0x00100000) {             /* underflow */
+            t = x*x;
+            if(t!=x) {          /* raise underflow flag */
+                INSERT_WORDS(y,hx,lx);
+                return y;
+            }
+        }
+        INSERT_WORDS(x,hx,lx);
+        return x;
+}
diff --git a/src/math/s_nextafterf.c b/src/math/s_nextafterf.c
new file mode 100644 (file)
index 0000000..7ce0883
--- /dev/null
@@ -0,0 +1,63 @@
+/* s_nextafterf.c -- float version of s_nextafter.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+nextafterf(float x, float y)
+{
+        volatile float t;
+        int32_t hx,hy,ix,iy;
+
+        GET_FLOAT_WORD(hx,x);
+        GET_FLOAT_WORD(hy,y);
+        ix = hx&0x7fffffff;             /* |x| */
+        iy = hy&0x7fffffff;             /* |y| */
+
+        if((ix>0x7f800000) ||   /* x is nan */
+           (iy>0x7f800000))     /* y is nan */
+           return x+y;
+        if(x==y) return y;              /* x=y, return y */
+        if(ix==0) {                             /* x == 0 */
+            SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
+            t = x*x;
+            if(t==x) return t; else return x;   /* raise underflow flag */
+        }
+        if(hx>=0) {                             /* x > 0 */
+            if(hx>hy) {                         /* x > y, x -= ulp */
+                hx -= 1;
+            } else {                            /* x < y, x += ulp */
+                hx += 1;
+            }
+        } else {                                /* x < 0 */
+            if(hy>=0||hx>hy){                   /* x < y, x -= ulp */
+                hx -= 1;
+            } else {                            /* x > y, x += ulp */
+                hx += 1;
+            }
+        }
+        hy = hx&0x7f800000;
+        if(hy>=0x7f800000) return x+x;  /* overflow  */
+        if(hy<0x00800000) {             /* underflow */
+            t = x*x;
+            if(t!=x) {          /* raise underflow flag */
+                SET_FLOAT_WORD(y,hx);
+                return y;
+            }
+        }
+        SET_FLOAT_WORD(x,hx);
+        return x;
+}
diff --git a/src/math/s_remquo.c b/src/math/s_remquo.c
new file mode 100644 (file)
index 0000000..1a2992d
--- /dev/null
@@ -0,0 +1,149 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double Zero[] = {0.0, -0.0,};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ */
+double
+remquo(double x, double y, int *quo)
+{
+        int32_t n,hx,hy,hz,ix,iy,sx,i;
+        uint32_t lx,ly,lz,q,sxy;
+
+        EXTRACT_WORDS(hx,lx,x);
+        EXTRACT_WORDS(hy,ly,y);
+        sxy = (hx ^ hy) & 0x80000000;
+        sx = hx&0x80000000;             /* sign of x */
+        hx ^=sx;                /* |x| */
+        hy &= 0x7fffffff;       /* |y| */
+
+    /* purge off exception values */
+        if((hy|ly)==0||(hx>=0x7ff00000)||       /* y=0,or x not finite */
+          ((hy|((ly|-ly)>>31))>0x7ff00000))     /* or y is NaN */
+            return (x*y)/(x*y);
+        if(hx<=hy) {
+            if((hx<hy)||(lx<ly)) {
+                q = 0;
+                goto fixup;     /* |x|<|y| return x or x-y */
+            }
+            if(lx==ly) {
+                *quo = 1;
+                return Zero[(uint32_t)sx>>31]; /* |x|=|y| return x*0*/
+            }
+        }
+
+    /* determine ix = ilogb(x) */
+        if(hx<0x00100000) {     /* subnormal x */
+            if(hx==0) {
+                for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+            } else {
+                for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+            }
+        } else ix = (hx>>20)-1023;
+
+    /* determine iy = ilogb(y) */
+        if(hy<0x00100000) {     /* subnormal y */
+            if(hy==0) {
+                for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+            } else {
+                for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+            }
+        } else iy = (hy>>20)-1023;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+        if(ix >= -1022) 
+            hx = 0x00100000|(0x000fffff&hx);
+        else {          /* subnormal x, shift x to normal */
+            n = -1022-ix;
+            if(n<=31) {
+                hx = (hx<<n)|(lx>>(32-n));
+                lx <<= n;
+            } else {
+                hx = lx<<(n-32);
+                lx = 0;
+            }
+        }
+        if(iy >= -1022) 
+            hy = 0x00100000|(0x000fffff&hy);
+        else {          /* subnormal y, shift y to normal */
+            n = -1022-iy;
+            if(n<=31) {
+                hy = (hy<<n)|(ly>>(32-n));
+                ly <<= n;
+            } else {
+                hy = ly<<(n-32);
+                ly = 0;
+            }
+        }
+
+    /* fix point fmod */
+        n = ix - iy;
+        q = 0;
+        while(n--) {
+            hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+            if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+            else {hx = hz+hz+(lz>>31); lx = lz+lz; q++;}
+            q <<= 1;
+        }
+        hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+        if(hz>=0) {hx=hz;lx=lz;q++;}
+
+    /* convert back to floating value and restore the sign */
+        if((hx|lx)==0) {                        /* return sign(x)*0 */
+            *quo = (sxy ? -q : q);
+            return Zero[(uint32_t)sx>>31];
+        }
+        while(hx<0x00100000) {          /* normalize x */
+            hx = hx+hx+(lx>>31); lx = lx+lx;
+            iy -= 1;
+        }
+        if(iy>= -1022) {        /* normalize output */
+            hx = ((hx-0x00100000)|((iy+1023)<<20));
+        } else {                /* subnormal output */
+            n = -1022 - iy;
+            if(n<=20) {
+                lx = (lx>>n)|((uint32_t)hx<<(32-n));
+                hx >>= n;
+            } else if (n<=31) {
+                lx = (hx<<(32-n))|(lx>>n); hx = sx;
+            } else {
+                lx = hx>>(n-32); hx = sx;
+            }
+        }
+fixup:
+        INSERT_WORDS(x,hx,lx);
+        y = fabs(y);
+        if (y < 0x1p-1021) {
+            if (x+x>y || (x+x==y && (q & 1))) {
+                q++;
+                x-=y;
+            }
+        } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+            q++;
+            x-=y;
+        }
+        GET_HIGH_WORD(hx,x);
+        SET_HIGH_WORD(x,hx^sx);
+        q &= 0x7fffffff;
+        *quo = (sxy ? -q : q);
+        return x;
+}
diff --git a/src/math/s_remquof.c b/src/math/s_remquof.c
new file mode 100644 (file)
index 0000000..be2a561
--- /dev/null
@@ -0,0 +1,118 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float Zero[] = {0.0, -0.0,};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ */
+float
+remquof(float x, float y, int *quo)
+{
+        int32_t n,hx,hy,hz,ix,iy,sx,i;
+        uint32_t q,sxy;
+
+        GET_FLOAT_WORD(hx,x);
+        GET_FLOAT_WORD(hy,y);
+        sxy = (hx ^ hy) & 0x80000000;
+        sx = hx&0x80000000;             /* sign of x */
+        hx ^=sx;                /* |x| */
+        hy &= 0x7fffffff;       /* |y| */
+
+    /* purge off exception values */
+        if(hy==0||hx>=0x7f800000||hy>0x7f800000) /* y=0,NaN;or x not finite */
+            return (x*y)/(x*y);
+        if(hx<hy) {
+            q = 0;
+            goto fixup; /* |x|<|y| return x or x-y */
+        } else if(hx==hy) {
+            *quo = 1;
+            return Zero[(uint32_t)sx>>31];     /* |x|=|y| return x*0*/
+        }
+
+    /* determine ix = ilogb(x) */
+        if(hx<0x00800000) {     /* subnormal x */
+            for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+        } else ix = (hx>>23)-127;
+
+    /* determine iy = ilogb(y) */
+        if(hy<0x00800000) {     /* subnormal y */
+            for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1;
+        } else iy = (hy>>23)-127;
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+        if(ix >= -126)
+            hx = 0x00800000|(0x007fffff&hx);
+        else {          /* subnormal x, shift x to normal */
+            n = -126-ix;
+            hx <<= n;
+        }
+        if(iy >= -126)
+            hy = 0x00800000|(0x007fffff&hy);
+        else {          /* subnormal y, shift y to normal */
+            n = -126-iy;
+            hy <<= n;
+        }
+
+    /* fix point fmod */
+        n = ix - iy;
+        q = 0;
+        while(n--) {
+            hz=hx-hy;
+            if(hz<0) hx = hx << 1;
+            else {hx = hz << 1; q++;}
+            q <<= 1;
+        }
+        hz=hx-hy;
+        if(hz>=0) {hx=hz;q++;}
+
+    /* convert back to floating value and restore the sign */
+        if(hx==0) {                             /* return sign(x)*0 */
+            *quo = (sxy ? -q : q);
+            return Zero[(uint32_t)sx>>31];
+        }
+        while(hx<0x00800000) {          /* normalize x */
+            hx <<= 1;
+            iy -= 1;
+        }
+        if(iy>= -126) {         /* normalize output */
+            hx = ((hx-0x00800000)|((iy+127)<<23));
+        } else {                /* subnormal output */
+            n = -126 - iy;
+            hx >>= n;
+        }
+fixup:
+        SET_FLOAT_WORD(x,hx);
+        y = fabsf(y);
+        if (y < 0x1p-125f) {
+            if (x+x>y || (x+x==y && (q & 1))) {
+                q++;
+                x-=y;
+            }
+        } else if (x>0.5f*y || (x==0.5f*y && (q & 1))) {
+            q++;
+            x-=y;
+        }
+        GET_FLOAT_WORD(hx,x);
+        SET_FLOAT_WORD(x,hx^sx);
+        q &= 0x7fffffff;
+        *quo = (sxy ? -q : q);
+        return x;
+}
diff --git a/src/math/s_rint.c b/src/math/s_rint.c
new file mode 100644 (file)
index 0000000..aec7d3c
--- /dev/null
@@ -0,0 +1,80 @@
+/* @(#)s_rint.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ *      Using floating addition.
+ * Exception:
+ *      Inexact flag raised if x not equal to rint(x).
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/*
+ * TWO23 is long double instead of double to avoid a bug in gcc.  Without
+ * this, gcc thinks that TWO23[sx]+x and w-TWO23[sx] already have double
+ * precision and doesn't clip them to double precision when they are
+ * assigned and returned.
+ */
+static const long double
+TWO52[2]={
+  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+double
+rint(double x)
+{
+        int32_t i0,j0,sx;
+        uint32_t i,i1;
+        double w,t;
+        EXTRACT_WORDS(i0,i1,x);
+        sx = (i0>>31)&1;
+        j0 = ((i0>>20)&0x7ff)-0x3ff;
+        if(j0<20) {
+            if(j0<0) {
+                if(((i0&0x7fffffff)|i1)==0) return x;
+                i1 |= (i0&0x0fffff);
+                i0 &= 0xfffe0000;
+                i0 |= ((i1|-i1)>>12)&0x80000;
+                SET_HIGH_WORD(x,i0);
+                w = TWO52[sx]+x;
+                t =  w-TWO52[sx];
+                GET_HIGH_WORD(i0,t);
+                SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+                return t;
+            } else {
+                i = (0x000fffff)>>j0;
+                if(((i0&i)|i1)==0) return x; /* x is integral */
+                i>>=1;
+                if(((i0&i)|i1)!=0) {
+                    if(j0==19) i1 = 0x40000000; else
+                    i0 = (i0&(~i))|((0x20000)>>j0);
+                }
+            }
+        } else if (j0>51) {
+            if(j0==0x400) return x+x;   /* inf or NaN */
+            else return x;              /* x is integral */
+        } else {
+            i = ((uint32_t)(0xffffffff))>>(j0-20);
+            if((i1&i)==0) return x;     /* x is integral */
+            i>>=1;
+            if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+        }
+        INSERT_WORDS(x,i0,i1);
+        w = TWO52[sx]+x;
+        return w-TWO52[sx];
+}
diff --git a/src/math/s_rintf.c b/src/math/s_rintf.c
new file mode 100644 (file)
index 0000000..c441870
--- /dev/null
@@ -0,0 +1,45 @@
+/* s_rintf.c -- float version of s_rint.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+TWO23[2]={
+  8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+};
+
+float
+rintf(float x)
+{
+        int32_t i0,j0,sx;
+        volatile float w,t;     /* volatile works around gcc bug */
+        GET_FLOAT_WORD(i0,x);
+        sx = (i0>>31)&1;
+        j0 = ((i0>>23)&0xff)-0x7f;
+        if(j0<23) {
+            if(j0<0) {
+                if((i0&0x7fffffff)==0) return x;
+                w = TWO23[sx]+x;
+                t =  w-TWO23[sx];
+                return t;
+            }
+            w = TWO23[sx]+x;
+            return w-TWO23[sx];
+        }
+        if(j0==0x80) return x+x;        /* inf or NaN */
+        else return x;                  /* x is integral */
+}
diff --git a/src/math/s_round.c b/src/math/s_round.c
new file mode 100644 (file)
index 0000000..d5bea7a
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <math.h>
+
+double
+round(double x)
+{
+       double t;
+
+       if (!isfinite(x))
+               return (x);
+
+       if (x >= 0.0) {
+               t = ceil(x);
+               if (t - x > 0.5)
+                       t -= 1.0;
+               return (t);
+       } else {
+               t = ceil(-x);
+               if (t + x > 0.5)
+                       t -= 1.0;
+               return (-t);
+       }
+}
diff --git a/src/math/s_roundf.c b/src/math/s_roundf.c
new file mode 100644 (file)
index 0000000..c4fc3e1
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <math.h>
+
+float
+roundf(float x)
+{
+       float t;
+
+       if (!isfinite(x))
+               return (x);
+
+       if (x >= 0.0) {
+               t = ceilf(x);
+               if (t - x > 0.5)
+                       t -= 1.0;
+               return (t);
+       } else {
+               t = ceilf(-x);
+               if (t + x > 0.5)
+                       t -= 1.0;
+               return (-t);
+       }
+}
diff --git a/src/math/s_scalbln.c b/src/math/s_scalbln.c
new file mode 100644 (file)
index 0000000..12b9391
--- /dev/null
@@ -0,0 +1,61 @@
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * scalbn (double x, int n)
+ * scalbn(x,n) returns x* 2**n  computed by  exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double
+two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge   = 1.0e+300,
+tiny   = 1.0e-300;
+
+double
+scalbln (double x, long n)
+{
+        int32_t k,hx,lx;
+        EXTRACT_WORDS(hx,lx,x);
+        k = (hx&0x7ff00000)>>20;                /* extract exponent */
+        if (k==0) {                             /* 0 or subnormal x */
+            if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+            x *= two54;
+            GET_HIGH_WORD(hx,x);
+            k = ((hx&0x7ff00000)>>20) - 54;
+            if (n< -50000) return tiny*x;       /*underflow*/
+            }
+        if (k==0x7ff) return x+x;               /* NaN or Inf */
+        k = k+n;
+        if (k >  0x7fe) return huge*copysign(huge,x); /* overflow  */
+        if (k > 0)                              /* normal result */
+            {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
+        if (k <= -54) {
+            if (n > 50000)      /* in case integer overflow in n+k */
+                return huge*copysign(huge,x);   /*overflow*/
+            else return tiny*copysign(tiny,x);  /*underflow*/
+        }
+        k += 54;                                /* subnormal result */
+        SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
+        return x*twom54;
+}
+
+double
+scalbn (double x, int n)
+{
+        return scalbln(x, n);
+}
diff --git a/src/math/s_scalblnf.c b/src/math/s_scalblnf.c
new file mode 100644 (file)
index 0000000..21e7641
--- /dev/null
@@ -0,0 +1,57 @@
+/* s_scalbnf.c -- float version of s_scalbn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float
+two25   =  3.355443200e+07,     /* 0x4c000000 */
+twom25  =  2.9802322388e-08,    /* 0x33000000 */
+huge   = 1.0e+30,
+tiny   = 1.0e-30;
+
+float
+scalblnf (float x, long n)
+{
+        int32_t k,ix;
+        GET_FLOAT_WORD(ix,x);
+        k = (ix&0x7f800000)>>23;                /* extract exponent */
+        if (k==0) {                             /* 0 or subnormal x */
+            if ((ix&0x7fffffff)==0) return x; /* +-0 */
+            x *= two25;
+            GET_FLOAT_WORD(ix,x);
+            k = ((ix&0x7f800000)>>23) - 25;
+            if (n< -50000) return tiny*x;       /*underflow*/
+            }
+        if (k==0xff) return x+x;                /* NaN or Inf */
+        k = k+n;
+        if (k >  0xfe) return huge*copysignf(huge,x); /* overflow  */
+        if (k > 0)                              /* normal result */
+            {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
+        if (k <= -25) {
+            if (n > 50000)      /* in case integer overflow in n+k */
+                return huge*copysignf(huge,x);  /*overflow*/
+            else return tiny*copysignf(tiny,x); /*underflow*/
+        }
+        k += 25;                                /* subnormal result */
+        SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
+        return x*twom25;
+}
+
+float
+scalbnf (float x, int n)
+{
+        return scalblnf(x, n);
+}
diff --git a/src/math/s_sin.c b/src/math/s_sin.c
new file mode 100644 (file)
index 0000000..2a2774e
--- /dev/null
@@ -0,0 +1,74 @@
+/* @(#)s_sin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ *      __kernel_sin            ... sine function on [-pi/4,pi/4]
+ *      __kernel_cos            ... cose function on [-pi/4,pi/4]
+ *      __ieee754_rem_pio2      ... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *      in [-pi/4 , +pi/4], and let n = k mod 4.
+ *      We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *          0          S           C             T
+ *          1          C          -S            -1/T
+ *          2         -S          -C             T
+ *          3         -C           S            -1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *      TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+sin(double x)
+{
+        double y[2],z=0.0;
+        int32_t n, ix;
+
+    /* High word of x. */
+        GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+        ix &= 0x7fffffff;
+        if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
+
+    /* sin(Inf or NaN) is NaN */
+        else if (ix>=0x7ff00000) return x-x;
+
+    /* argument reduction needed */
+        else {
+            n = __ieee754_rem_pio2(x,y);
+            switch(n&3) {
+                case 0: return  __kernel_sin(y[0],y[1],1);
+                case 1: return  __kernel_cos(y[0],y[1]);
+                case 2: return -__kernel_sin(y[0],y[1],1);
+                default:
+                        return -__kernel_cos(y[0],y[1]);
+            }
+        }
+}
diff --git a/src/math/s_sinf.c b/src/math/s_sinf.c
new file mode 100644 (file)
index 0000000..d2b8e80
--- /dev/null
@@ -0,0 +1,45 @@
+/* s_sinf.c -- float version of s_sin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+sinf(float x)
+{
+        float y[2],z=0.0;
+        int32_t n, ix;
+
+        GET_FLOAT_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+        ix &= 0x7fffffff;
+        if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
+
+    /* sin(Inf or NaN) is NaN */
+        else if (ix>=0x7f800000) return x-x;
+
+    /* argument reduction needed */
+        else {
+            n = __ieee754_rem_pio2f(x,y);
+            switch(n&3) {
+                case 0: return  __kernel_sinf(y[0],y[1],1);
+                case 1: return  __kernel_cosf(y[0],y[1]);
+                case 2: return -__kernel_sinf(y[0],y[1],1);
+                default:
+                        return -__kernel_cosf(y[0],y[1]);
+            }
+        }
+}
diff --git a/src/math/s_tan.c b/src/math/s_tan.c
new file mode 100644 (file)
index 0000000..3333cb3
--- /dev/null
@@ -0,0 +1,68 @@
+/* @(#)s_tan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ *      __kernel_tan            ... tangent function on [-pi/4,pi/4]
+ *      __ieee754_rem_pio2      ... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *      in [-pi/4 , +pi/4], and let n = k mod 4.
+ *      We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *          0          S           C             T
+ *          1          C          -S            -1/T
+ *          2         -S          -C             T
+ *          3         -C           S            -1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *      TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+double
+tan(double x)
+{
+        double y[2],z=0.0;
+        int32_t n, ix;
+
+    /* High word of x. */
+        GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+        ix &= 0x7fffffff;
+        if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1);
+
+    /* tan(Inf or NaN) is NaN */
+        else if (ix>=0x7ff00000) return x-x;            /* NaN */
+
+    /* argument reduction needed */
+        else {
+            n = __ieee754_rem_pio2(x,y);
+            return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
+                                                        -1 -- n odd */
+        }
+}
diff --git a/src/math/s_tanf.c b/src/math/s_tanf.c
new file mode 100644 (file)
index 0000000..660dd9c
--- /dev/null
@@ -0,0 +1,40 @@
+/* s_tanf.c -- float version of s_tan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+float
+tanf(float x)
+{
+        float y[2],z=0.0;
+        int32_t n, ix;
+
+        GET_FLOAT_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+        ix &= 0x7fffffff;
+        if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1);
+
+    /* tan(Inf or NaN) is NaN */
+        else if (ix>=0x7f800000) return x-x;            /* NaN */
+
+    /* argument reduction needed */
+        else {
+            n = __ieee754_rem_pio2f(x,y);
+            return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
+                                                              -1 -- n odd */
+        }
+}
diff --git a/src/math/s_tanh.c b/src/math/s_tanh.c
new file mode 100644 (file)
index 0000000..78b8e84
--- /dev/null
@@ -0,0 +1,74 @@
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Tanh(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ *                                     x    -x
+ *                                    e  - e
+ *      0. tanh(x) is defined to be -----------
+ *                                     x    -x
+ *                                    e  + e
+ *      1. reduce x to non-negative by tanh(-x) = -tanh(x).
+ *      2.  0      <= x <= 2**-55 : tanh(x) := x*(one+x)
+ *                                              -t
+ *          2**-55 <  x <=  1     : tanh(x) := -----; t = expm1(-2x)
+ *                                             t + 2
+ *                                                   2
+ *          1      <= x <=  22.0  : tanh(x) := 1-  ----- ; t=expm1(2x)
+ *                                                 t + 2
+ *          22.0   <  x <= INF    : tanh(x) := 1.
+ *
+ * Special cases:
+ *      tanh(NaN) is NaN;
+ *      only tanh(0)=0 is exact for finite argument.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one=1.0, two=2.0, tiny = 1.0e-300;
+
+double
+tanh(double x)
+{
+        double t,z;
+        int32_t jx,ix;
+
+    /* High word of |x|. */
+        GET_HIGH_WORD(jx,x);
+        ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+        if(ix>=0x7ff00000) {
+            if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
+            else       return one/x-one;    /* tanh(NaN) = NaN */
+        }
+
+    /* |x| < 22 */
+        if (ix < 0x40360000) {          /* |x|<22 */
+            if (ix<0x3c800000)          /* |x|<2**-55 */
+                return x*(one+x);       /* tanh(small) = small */
+            if (ix>=0x3ff00000) {       /* |x|>=1  */
+                t = expm1(two*fabs(x));
+                z = one - two/(t+two);
+            } else {
+                t = expm1(-two*fabs(x));
+                z= -t/(t+two);
+            }
+    /* |x| > 22, return +-1 */
+        } else {
+            z = one - tiny;             /* raised inexact flag */
+        }
+        return (jx>=0)? z: -z;
+}
diff --git a/src/math/s_tanhf.c b/src/math/s_tanhf.c
new file mode 100644 (file)
index 0000000..a082040
--- /dev/null
@@ -0,0 +1,52 @@
+/* s_tanhf.c -- float version of s_tanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float one=1.0, two=2.0, tiny = 1.0e-30;
+
+float
+tanhf(float x)
+{
+        float t,z;
+        int32_t jx,ix;
+
+        GET_FLOAT_WORD(jx,x);
+        ix = jx&0x7fffffff;
+
+    /* x is INF or NaN */
+        if(ix>=0x7f800000) {
+            if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
+            else       return one/x-one;    /* tanh(NaN) = NaN */
+        }
+
+    /* |x| < 22 */
+        if (ix < 0x41b00000) {          /* |x|<22 */
+            if (ix<0x24000000)          /* |x|<2**-55 */
+                return x*(one+x);       /* tanh(small) = small */
+            if (ix>=0x3f800000) {       /* |x|>=1  */
+                t = expm1f(two*fabsf(x));
+                z = one - two/(t+two);
+            } else {
+                t = expm1f(-two*fabsf(x));
+                z= -t/(t+two);
+            }
+    /* |x| > 22, return +-1 */
+        } else {
+            z = one - tiny;             /* raised inexact flag */
+        }
+        return (jx>=0)? z: -z;
+}
diff --git a/src/math/s_trunc.c b/src/math/s_trunc.c
new file mode 100644 (file)
index 0000000..02c6556
--- /dev/null
@@ -0,0 +1,58 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * trunc(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *      Bit twiddling.
+ * Exception:
+ *      Inexact flag raised if x not equal to trunc(x).
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double
+trunc(double x)
+{
+        int32_t i0,i1,j0;
+        uint32_t i,j;
+        EXTRACT_WORDS(i0,i1,x);
+        j0 = ((i0>>20)&0x7ff)-0x3ff;
+        if(j0<20) {
+            if(j0<0) {  /* raise inexact if x != 0 */
+                if(huge+x>0.0) {/* |x|<1, so return 0*sign(x) */
+                    i0 &= 0x80000000U;
+                    i1 = 0;
+                }
+            } else {
+                i = (0x000fffff)>>j0;
+                if(((i0&i)|i1)==0) return x; /* x is integral */
+                if(huge+x>0.0) {        /* raise inexact flag */
+                    i0 &= (~i); i1=0;
+                }
+            }
+        } else if (j0>51) {
+            if(j0==0x400) return x+x;   /* inf or NaN */
+            else return x;              /* x is integral */
+        } else {
+            i = ((uint32_t)(0xffffffff))>>(j0-20);
+            if((i1&i)==0) return x;     /* x is integral */
+            if(huge+x>0.0)              /* raise inexact flag */
+                i1 &= (~i);
+        }
+        INSERT_WORDS(x,i0,i1);
+        return x;
+}
diff --git a/src/math/s_truncf.c b/src/math/s_truncf.c
new file mode 100644 (file)
index 0000000..c253e62
--- /dev/null
@@ -0,0 +1,50 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * truncf(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *      Bit twiddling.
+ * Exception:
+ *      Inexact flag raised if x not equal to truncf(x).
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const float huge = 1.0e30F;
+
+float
+truncf(float x)
+{
+        int32_t i0,j0;
+        uint32_t i;
+        GET_FLOAT_WORD(i0,x);
+        j0 = ((i0>>23)&0xff)-0x7f;
+        if(j0<23) {
+            if(j0<0) {  /* raise inexact if x != 0 */
+                if(huge+x>0.0F)         /* |x|<1, so return 0*sign(x) */
+                    i0 &= 0x80000000;
+            } else {
+                i = (0x007fffff)>>j0;
+                if((i0&i)==0) return x; /* x is integral */
+                if(huge+x>0.0F)         /* raise inexact flag */
+                    i0 &= (~i);
+            }
+        } else {
+            if(j0==0x80) return x+x;    /* inf or NaN */
+            else return x;              /* x is integral */
+        }
+        SET_FLOAT_WORD(x,i0);
+        return x;
+}
diff --git a/src/misc/basename.c b/src/misc/basename.c
new file mode 100644 (file)
index 0000000..c87e00c
--- /dev/null
@@ -0,0 +1,12 @@
+#include <string.h>
+#include <libgen.h>
+
+char *basename(char *s)
+{
+       size_t i;
+       if (!s || !*s) return ".";
+       i = strlen(s)-1;
+       for (; i&&s[i]=='/'; i--) s[i] = 0;
+       for (; i&&s[i-1]!='/'; i--);
+       return s+i;
+}
diff --git a/src/misc/bswap_32.c b/src/misc/bswap_32.c
new file mode 100644 (file)
index 0000000..a2418ca
--- /dev/null
@@ -0,0 +1,7 @@
+#include <endian.h>
+#include <stdint.h>
+
+uint32_t bswap_32(uint32_t x)
+{
+       return x>>24 | x>>16&0xff00 | x<<16&0xff0000 | x<<24;
+}
diff --git a/src/misc/bswap_64.c b/src/misc/bswap_64.c
new file mode 100644 (file)
index 0000000..961300b
--- /dev/null
@@ -0,0 +1,9 @@
+#include <endian.h>
+#include <stdint.h>
+
+uint32_t bswap_32(uint32_t);
+
+uint64_t bswap_64(uint64_t x)
+{
+       return bswap_32(x)+0LL<<32 | bswap_32(x>>32);
+}
diff --git a/src/misc/crypt.c b/src/misc/crypt.c
new file mode 100644 (file)
index 0000000..42918ef
--- /dev/null
@@ -0,0 +1,2578 @@
+/*
+ * FreeSec: libcrypt for NetBSD
+ *
+ * Copyright (c) 1994 David Burren
+ * 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. Neither the name of the author nor the names of other contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 is an original implementation of the DES and the crypt(3) interfaces
+ * by David Burren <davidb@werj.com.au>.
+ *
+ * An excellent reference on the underlying algorithm (and related
+ * algorithms) is:
+ *
+ *     B. Schneier, Applied Cryptography: protocols, algorithms,
+ *     and source code in C, John Wiley & Sons, 1994.
+ *
+ * Note that in that book's description of DES the lookups for the initial,
+ * pbox, and final permutations are inverted (this has been brought to the
+ * attention of the author).  A list of errata for this book has been
+ * posted to the sci.crypt newsgroup by the author and is available for FTP.
+ *
+ * ARCHITECTURE ASSUMPTIONS:
+ *     It is assumed that the 8-byte arrays passed by reference can be
+ *     addressed as arrays of uint32_t's (ie. the CPU is not picky about
+ *     alignment).
+ */
+
+#include <stdint.h>
+#include "libc.h"
+
+static int i64c(int i)
+{
+       i &= 0x3f;
+       if (i == 0)
+               return '.';
+       if (i == 1)
+               return '/';
+       if (i < 12)
+               return ('0' - 2 + i);
+       if (i < 38)
+               return ('A' - 12 + i);
+       return ('a' - 38 + i);
+}
+
+/* Generated by const_des_init() (removed) */
+
+static const uint8_t final_perm[64] = {
+       0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3b, 0x33, 0x2b, 0x23, 0x1b, 0x13, 0x0b, 0x03,
+       0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05, 0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f, 0x07,
+       0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x00, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02,
+       0x3c, 0x34, 0x2c, 0x24, 0x1c, 0x14, 0x0c, 0x04, 0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06,
+};
+static const uint8_t m_sbox[4][4096] = {
+       {
+               0xef, 0xe3, 0xe1, 0xed, 0xe8, 0xe4, 0xee, 0xe7,
+               0xe6, 0xef, 0xeb, 0xe2, 0xe3, 0xe8, 0xe4, 0xee,
+               0xe9, 0xec, 0xe7, 0xe0, 0xe2, 0xe1, 0xed, 0xea,
+               0xec, 0xe6, 0xe0, 0xe9, 0xe5, 0xeb, 0xea, 0xe5,
+               0xe0, 0xed, 0xee, 0xe8, 0xe7, 0xea, 0xeb, 0xe1,
+               0xea, 0xe3, 0xe4, 0xef, 0xed, 0xe4, 0xe1, 0xe2,
+               0xe5, 0xeb, 0xe8, 0xe6, 0xec, 0xe7, 0xe6, 0xec,
+               0xe9, 0xe0, 0xe3, 0xe5, 0xe2, 0xee, 0xef, 0xe9,
+               0x0f, 0x03, 0x01, 0x0d, 0x08, 0x04, 0x0e, 0x07,
+               0x06, 0x0f, 0x0b, 0x02, 0x03, 0x08, 0x04, 0x0e,
+               0x09, 0x0c, 0x07, 0x00, 0x02, 0x01, 0x0d, 0x0a,
+               0x0c, 0x06, 0x00, 0x09, 0x05, 0x0b, 0x0a, 0x05,
+               0x00, 0x0d, 0x0e, 0x08, 0x07, 0x0a, 0x0b, 0x01,
+               0x0a, 0x03, 0x04, 0x0f, 0x0d, 0x04, 0x01, 0x02,
+               0x05, 0x0b, 0x08, 0x06, 0x0c, 0x07, 0x06, 0x0c,
+               0x09, 0x00, 0x03, 0x05, 0x02, 0x0e, 0x0f, 0x09,
+               0x4f, 0x43, 0x41, 0x4d, 0x48, 0x44, 0x4e, 0x47,
+               0x46, 0x4f, 0x4b, 0x42, 0x43, 0x48, 0x44, 0x4e,
+               0x49, 0x4c, 0x47, 0x40, 0x42, 0x41, 0x4d, 0x4a,
+               0x4c, 0x46, 0x40, 0x49, 0x45, 0x4b, 0x4a, 0x45,
+               0x40, 0x4d, 0x4e, 0x48, 0x47, 0x4a, 0x4b, 0x41,
+               0x4a, 0x43, 0x44, 0x4f, 0x4d, 0x44, 0x41, 0x42,
+               0x45, 0x4b, 0x48, 0x46, 0x4c, 0x47, 0x46, 0x4c,
+               0x49, 0x40, 0x43, 0x45, 0x42, 0x4e, 0x4f, 0x49,
+               0xff, 0xf3, 0xf1, 0xfd, 0xf8, 0xf4, 0xfe, 0xf7,
+               0xf6, 0xff, 0xfb, 0xf2, 0xf3, 0xf8, 0xf4, 0xfe,
+               0xf9, 0xfc, 0xf7, 0xf0, 0xf2, 0xf1, 0xfd, 0xfa,
+               0xfc, 0xf6, 0xf0, 0xf9, 0xf5, 0xfb, 0xfa, 0xf5,
+               0xf0, 0xfd, 0xfe, 0xf8, 0xf7, 0xfa, 0xfb, 0xf1,
+               0xfa, 0xf3, 0xf4, 0xff, 0xfd, 0xf4, 0xf1, 0xf2,
+               0xf5, 0xfb, 0xf8, 0xf6, 0xfc, 0xf7, 0xf6, 0xfc,
+               0xf9, 0xf0, 0xf3, 0xf5, 0xf2, 0xfe, 0xff, 0xf9,
+               0xdf, 0xd3, 0xd1, 0xdd, 0xd8, 0xd4, 0xde, 0xd7,
+               0xd6, 0xdf, 0xdb, 0xd2, 0xd3, 0xd8, 0xd4, 0xde,
+               0xd9, 0xdc, 0xd7, 0xd0, 0xd2, 0xd1, 0xdd, 0xda,
+               0xdc, 0xd6, 0xd0, 0xd9, 0xd5, 0xdb, 0xda, 0xd5,
+               0xd0, 0xdd, 0xde, 0xd8, 0xd7, 0xda, 0xdb, 0xd1,
+               0xda, 0xd3, 0xd4, 0xdf, 0xdd, 0xd4, 0xd1, 0xd2,
+               0xd5, 0xdb, 0xd8, 0xd6, 0xdc, 0xd7, 0xd6, 0xdc,
+               0xd9, 0xd0, 0xd3, 0xd5, 0xd2, 0xde, 0xdf, 0xd9,
+               0x7f, 0x73, 0x71, 0x7d, 0x78, 0x74, 0x7e, 0x77,
+               0x76, 0x7f, 0x7b, 0x72, 0x73, 0x78, 0x74, 0x7e,
+               0x79, 0x7c, 0x77, 0x70, 0x72, 0x71, 0x7d, 0x7a,
+               0x7c, 0x76, 0x70, 0x79, 0x75, 0x7b, 0x7a, 0x75,
+               0x70, 0x7d, 0x7e, 0x78, 0x77, 0x7a, 0x7b, 0x71,
+               0x7a, 0x73, 0x74, 0x7f, 0x7d, 0x74, 0x71, 0x72,
+               0x75, 0x7b, 0x78, 0x76, 0x7c, 0x77, 0x76, 0x7c,
+               0x79, 0x70, 0x73, 0x75, 0x72, 0x7e, 0x7f, 0x79,
+               0x1f, 0x13, 0x11, 0x1d, 0x18, 0x14, 0x1e, 0x17,
+               0x16, 0x1f, 0x1b, 0x12, 0x13, 0x18, 0x14, 0x1e,
+               0x19, 0x1c, 0x17, 0x10, 0x12, 0x11, 0x1d, 0x1a,
+               0x1c, 0x16, 0x10, 0x19, 0x15, 0x1b, 0x1a, 0x15,
+               0x10, 0x1d, 0x1e, 0x18, 0x17, 0x1a, 0x1b, 0x11,
+               0x1a, 0x13, 0x14, 0x1f, 0x1d, 0x14, 0x11, 0x12,
+               0x15, 0x1b, 0x18, 0x16, 0x1c, 0x17, 0x16, 0x1c,
+               0x19, 0x10, 0x13, 0x15, 0x12, 0x1e, 0x1f, 0x19,
+               0x4f, 0x43, 0x41, 0x4d, 0x48, 0x44, 0x4e, 0x47,
+               0x46, 0x4f, 0x4b, 0x42, 0x43, 0x48, 0x44, 0x4e,
+               0x49, 0x4c, 0x47, 0x40, 0x42, 0x41, 0x4d, 0x4a,
+               0x4c, 0x46, 0x40, 0x49, 0x45, 0x4b, 0x4a, 0x45,
+               0x40, 0x4d, 0x4e, 0x48, 0x47, 0x4a, 0x4b, 0x41,
+               0x4a, 0x43, 0x44, 0x4f, 0x4d, 0x44, 0x41, 0x42,
+               0x45, 0x4b, 0x48, 0x46, 0x4c, 0x47, 0x46, 0x4c,
+               0x49, 0x40, 0x43, 0x45, 0x42, 0x4e, 0x4f, 0x49,
+               0x2f, 0x23, 0x21, 0x2d, 0x28, 0x24, 0x2e, 0x27,
+               0x26, 0x2f, 0x2b, 0x22, 0x23, 0x28, 0x24, 0x2e,
+               0x29, 0x2c, 0x27, 0x20, 0x22, 0x21, 0x2d, 0x2a,
+               0x2c, 0x26, 0x20, 0x29, 0x25, 0x2b, 0x2a, 0x25,
+               0x20, 0x2d, 0x2e, 0x28, 0x27, 0x2a, 0x2b, 0x21,
+               0x2a, 0x23, 0x24, 0x2f, 0x2d, 0x24, 0x21, 0x22,
+               0x25, 0x2b, 0x28, 0x26, 0x2c, 0x27, 0x26, 0x2c,
+               0x29, 0x20, 0x23, 0x25, 0x22, 0x2e, 0x2f, 0x29,
+               0xef, 0xe3, 0xe1, 0xed, 0xe8, 0xe4, 0xee, 0xe7,
+               0xe6, 0xef, 0xeb, 0xe2, 0xe3, 0xe8, 0xe4, 0xee,
+               0xe9, 0xec, 0xe7, 0xe0, 0xe2, 0xe1, 0xed, 0xea,
+               0xec, 0xe6, 0xe0, 0xe9, 0xe5, 0xeb, 0xea, 0xe5,
+               0xe0, 0xed, 0xee, 0xe8, 0xe7, 0xea, 0xeb, 0xe1,
+               0xea, 0xe3, 0xe4, 0xef, 0xed, 0xe4, 0xe1, 0xe2,
+               0xe5, 0xeb, 0xe8, 0xe6, 0xec, 0xe7, 0xe6, 0xec,
+               0xe9, 0xe0, 0xe3, 0xe5, 0xe2, 0xee, 0xef, 0xe9,
+               0xff, 0xf3, 0xf1, 0xfd, 0xf8, 0xf4, 0xfe, 0xf7,
+               0xf6, 0xff, 0xfb, 0xf2, 0xf3, 0xf8, 0xf4, 0xfe,
+               0xf9, 0xfc, 0xf7, 0xf0, 0xf2, 0xf1, 0xfd, 0xfa,
+               0xfc, 0xf6, 0xf0, 0xf9, 0xf5, 0xfb, 0xfa, 0xf5,
+               0xf0, 0xfd, 0xfe, 0xf8, 0xf7, 0xfa, 0xfb, 0xf1,
+               0xfa, 0xf3, 0xf4, 0xff, 0xfd, 0xf4, 0xf1, 0xf2,
+               0xf5, 0xfb, 0xf8, 0xf6, 0xfc, 0xf7, 0xf6, 0xfc,
+               0xf9, 0xf0, 0xf3, 0xf5, 0xf2, 0xfe, 0xff, 0xf9,
+               0x2f, 0x23, 0x21, 0x2d, 0x28, 0x24, 0x2e, 0x27,
+               0x26, 0x2f, 0x2b, 0x22, 0x23, 0x28, 0x24, 0x2e,
+               0x29, 0x2c, 0x27, 0x20, 0x22, 0x21, 0x2d, 0x2a,
+               0x2c, 0x26, 0x20, 0x29, 0x25, 0x2b, 0x2a, 0x25,
+               0x20, 0x2d, 0x2e, 0x28, 0x27, 0x2a, 0x2b, 0x21,
+               0x2a, 0x23, 0x24, 0x2f, 0x2d, 0x24, 0x21, 0x22,
+               0x25, 0x2b, 0x28, 0x26, 0x2c, 0x27, 0x26, 0x2c,
+               0x29, 0x20, 0x23, 0x25, 0x22, 0x2e, 0x2f, 0x29,
+               0xbf, 0xb3, 0xb1, 0xbd, 0xb8, 0xb4, 0xbe, 0xb7,
+               0xb6, 0xbf, 0xbb, 0xb2, 0xb3, 0xb8, 0xb4, 0xbe,
+               0xb9, 0xbc, 0xb7, 0xb0, 0xb2, 0xb1, 0xbd, 0xba,
+               0xbc, 0xb6, 0xb0, 0xb9, 0xb5, 0xbb, 0xba, 0xb5,
+               0xb0, 0xbd, 0xbe, 0xb8, 0xb7, 0xba, 0xbb, 0xb1,
+               0xba, 0xb3, 0xb4, 0xbf, 0xbd, 0xb4, 0xb1, 0xb2,
+               0xb5, 0xbb, 0xb8, 0xb6, 0xbc, 0xb7, 0xb6, 0xbc,
+               0xb9, 0xb0, 0xb3, 0xb5, 0xb2, 0xbe, 0xbf, 0xb9,
+               0xdf, 0xd3, 0xd1, 0xdd, 0xd8, 0xd4, 0xde, 0xd7,
+               0xd6, 0xdf, 0xdb, 0xd2, 0xd3, 0xd8, 0xd4, 0xde,
+               0xd9, 0xdc, 0xd7, 0xd0, 0xd2, 0xd1, 0xdd, 0xda,
+               0xdc, 0xd6, 0xd0, 0xd9, 0xd5, 0xdb, 0xda, 0xd5,
+               0xd0, 0xdd, 0xde, 0xd8, 0xd7, 0xda, 0xdb, 0xd1,
+               0xda, 0xd3, 0xd4, 0xdf, 0xdd, 0xd4, 0xd1, 0xd2,
+               0xd5, 0xdb, 0xd8, 0xd6, 0xdc, 0xd7, 0xd6, 0xdc,
+               0xd9, 0xd0, 0xd3, 0xd5, 0xd2, 0xde, 0xdf, 0xd9,
+               0x8f, 0x83, 0x81, 0x8d, 0x88, 0x84, 0x8e, 0x87,
+               0x86, 0x8f, 0x8b, 0x82, 0x83, 0x88, 0x84, 0x8e,
+               0x89, 0x8c, 0x87, 0x80, 0x82, 0x81, 0x8d, 0x8a,
+               0x8c, 0x86, 0x80, 0x89, 0x85, 0x8b, 0x8a, 0x85,
+               0x80, 0x8d, 0x8e, 0x88, 0x87, 0x8a, 0x8b, 0x81,
+               0x8a, 0x83, 0x84, 0x8f, 0x8d, 0x84, 0x81, 0x82,
+               0x85, 0x8b, 0x88, 0x86, 0x8c, 0x87, 0x86, 0x8c,
+               0x89, 0x80, 0x83, 0x85, 0x82, 0x8e, 0x8f, 0x89,
+               0x1f, 0x13, 0x11, 0x1d, 0x18, 0x14, 0x1e, 0x17,
+               0x16, 0x1f, 0x1b, 0x12, 0x13, 0x18, 0x14, 0x1e,
+               0x19, 0x1c, 0x17, 0x10, 0x12, 0x11, 0x1d, 0x1a,
+               0x1c, 0x16, 0x10, 0x19, 0x15, 0x1b, 0x1a, 0x15,
+               0x10, 0x1d, 0x1e, 0x18, 0x17, 0x1a, 0x1b, 0x11,
+               0x1a, 0x13, 0x14, 0x1f, 0x1d, 0x14, 0x11, 0x12,
+               0x15, 0x1b, 0x18, 0x16, 0x1c, 0x17, 0x16, 0x1c,
+               0x19, 0x10, 0x13, 0x15, 0x12, 0x1e, 0x1f, 0x19,
+               0x3f, 0x33, 0x31, 0x3d, 0x38, 0x34, 0x3e, 0x37,
+               0x36, 0x3f, 0x3b, 0x32, 0x33, 0x38, 0x34, 0x3e,
+               0x39, 0x3c, 0x37, 0x30, 0x32, 0x31, 0x3d, 0x3a,
+               0x3c, 0x36, 0x30, 0x39, 0x35, 0x3b, 0x3a, 0x35,
+               0x30, 0x3d, 0x3e, 0x38, 0x37, 0x3a, 0x3b, 0x31,
+               0x3a, 0x33, 0x34, 0x3f, 0x3d, 0x34, 0x31, 0x32,
+               0x35, 0x3b, 0x38, 0x36, 0x3c, 0x37, 0x36, 0x3c,
+               0x39, 0x30, 0x33, 0x35, 0x32, 0x3e, 0x3f, 0x39,
+               0xaf, 0xa3, 0xa1, 0xad, 0xa8, 0xa4, 0xae, 0xa7,
+               0xa6, 0xaf, 0xab, 0xa2, 0xa3, 0xa8, 0xa4, 0xae,
+               0xa9, 0xac, 0xa7, 0xa0, 0xa2, 0xa1, 0xad, 0xaa,
+               0xac, 0xa6, 0xa0, 0xa9, 0xa5, 0xab, 0xaa, 0xa5,
+               0xa0, 0xad, 0xae, 0xa8, 0xa7, 0xaa, 0xab, 0xa1,
+               0xaa, 0xa3, 0xa4, 0xaf, 0xad, 0xa4, 0xa1, 0xa2,
+               0xa5, 0xab, 0xa8, 0xa6, 0xac, 0xa7, 0xa6, 0xac,
+               0xa9, 0xa0, 0xa3, 0xa5, 0xa2, 0xae, 0xaf, 0xa9,
+               0xaf, 0xa3, 0xa1, 0xad, 0xa8, 0xa4, 0xae, 0xa7,
+               0xa6, 0xaf, 0xab, 0xa2, 0xa3, 0xa8, 0xa4, 0xae,
+               0xa9, 0xac, 0xa7, 0xa0, 0xa2, 0xa1, 0xad, 0xaa,
+               0xac, 0xa6, 0xa0, 0xa9, 0xa5, 0xab, 0xaa, 0xa5,
+               0xa0, 0xad, 0xae, 0xa8, 0xa7, 0xaa, 0xab, 0xa1,
+               0xaa, 0xa3, 0xa4, 0xaf, 0xad, 0xa4, 0xa1, 0xa2,
+               0xa5, 0xab, 0xa8, 0xa6, 0xac, 0xa7, 0xa6, 0xac,
+               0xa9, 0xa0, 0xa3, 0xa5, 0xa2, 0xae, 0xaf, 0xa9,
+               0x6f, 0x63, 0x61, 0x6d, 0x68, 0x64, 0x6e, 0x67,
+               0x66, 0x6f, 0x6b, 0x62, 0x63, 0x68, 0x64, 0x6e,
+               0x69, 0x6c, 0x67, 0x60, 0x62, 0x61, 0x6d, 0x6a,
+               0x6c, 0x66, 0x60, 0x69, 0x65, 0x6b, 0x6a, 0x65,
+               0x60, 0x6d, 0x6e, 0x68, 0x67, 0x6a, 0x6b, 0x61,
+               0x6a, 0x63, 0x64, 0x6f, 0x6d, 0x64, 0x61, 0x62,
+               0x65, 0x6b, 0x68, 0x66, 0x6c, 0x67, 0x66, 0x6c,
+               0x69, 0x60, 0x63, 0x65, 0x62, 0x6e, 0x6f, 0x69,
+               0x6f, 0x63, 0x61, 0x6d, 0x68, 0x64, 0x6e, 0x67,
+               0x66, 0x6f, 0x6b, 0x62, 0x63, 0x68, 0x64, 0x6e,
+               0x69, 0x6c, 0x67, 0x60, 0x62, 0x61, 0x6d, 0x6a,
+               0x6c, 0x66, 0x60, 0x69, 0x65, 0x6b, 0x6a, 0x65,
+               0x60, 0x6d, 0x6e, 0x68, 0x67, 0x6a, 0x6b, 0x61,
+               0x6a, 0x63, 0x64, 0x6f, 0x6d, 0x64, 0x61, 0x62,
+               0x65, 0x6b, 0x68, 0x66, 0x6c, 0x67, 0x66, 0x6c,
+               0x69, 0x60, 0x63, 0x65, 0x62, 0x6e, 0x6f, 0x69,
+               0xcf, 0xc3, 0xc1, 0xcd, 0xc8, 0xc4, 0xce, 0xc7,
+               0xc6, 0xcf, 0xcb, 0xc2, 0xc3, 0xc8, 0xc4, 0xce,
+               0xc9, 0xcc, 0xc7, 0xc0, 0xc2, 0xc1, 0xcd, 0xca,
+               0xcc, 0xc6, 0xc0, 0xc9, 0xc5, 0xcb, 0xca, 0xc5,
+               0xc0, 0xcd, 0xce, 0xc8, 0xc7, 0xca, 0xcb, 0xc1,
+               0xca, 0xc3, 0xc4, 0xcf, 0xcd, 0xc4, 0xc1, 0xc2,
+               0xc5, 0xcb, 0xc8, 0xc6, 0xcc, 0xc7, 0xc6, 0xcc,
+               0xc9, 0xc0, 0xc3, 0xc5, 0xc2, 0xce, 0xcf, 0xc9,
+               0xcf, 0xc3, 0xc1, 0xcd, 0xc8, 0xc4, 0xce, 0xc7,
+               0xc6, 0xcf, 0xcb, 0xc2, 0xc3, 0xc8, 0xc4, 0xce,
+               0xc9, 0xcc, 0xc7, 0xc0, 0xc2, 0xc1, 0xcd, 0xca,
+               0xcc, 0xc6, 0xc0, 0xc9, 0xc5, 0xcb, 0xca, 0xc5,
+               0xc0, 0xcd, 0xce, 0xc8, 0xc7, 0xca, 0xcb, 0xc1,
+               0xca, 0xc3, 0xc4, 0xcf, 0xcd, 0xc4, 0xc1, 0xc2,
+               0xc5, 0xcb, 0xc8, 0xc6, 0xcc, 0xc7, 0xc6, 0xcc,
+               0xc9, 0xc0, 0xc3, 0xc5, 0xc2, 0xce, 0xcf, 0xc9,
+               0xbf, 0xb3, 0xb1, 0xbd, 0xb8, 0xb4, 0xbe, 0xb7,
+               0xb6, 0xbf, 0xbb, 0xb2, 0xb3, 0xb8, 0xb4, 0xbe,
+               0xb9, 0xbc, 0xb7, 0xb0, 0xb2, 0xb1, 0xbd, 0xba,
+               0xbc, 0xb6, 0xb0, 0xb9, 0xb5, 0xbb, 0xba, 0xb5,
+               0xb0, 0xbd, 0xbe, 0xb8, 0xb7, 0xba, 0xbb, 0xb1,
+               0xba, 0xb3, 0xb4, 0xbf, 0xbd, 0xb4, 0xb1, 0xb2,
+               0xb5, 0xbb, 0xb8, 0xb6, 0xbc, 0xb7, 0xb6, 0xbc,
+               0xb9, 0xb0, 0xb3, 0xb5, 0xb2, 0xbe, 0xbf, 0xb9,
+               0x5f, 0x53, 0x51, 0x5d, 0x58, 0x54, 0x5e, 0x57,
+               0x56, 0x5f, 0x5b, 0x52, 0x53, 0x58, 0x54, 0x5e,
+               0x59, 0x5c, 0x57, 0x50, 0x52, 0x51, 0x5d, 0x5a,
+               0x5c, 0x56, 0x50, 0x59, 0x55, 0x5b, 0x5a, 0x55,
+               0x50, 0x5d, 0x5e, 0x58, 0x57, 0x5a, 0x5b, 0x51,
+               0x5a, 0x53, 0x54, 0x5f, 0x5d, 0x54, 0x51, 0x52,
+               0x55, 0x5b, 0x58, 0x56, 0x5c, 0x57, 0x56, 0x5c,
+               0x59, 0x50, 0x53, 0x55, 0x52, 0x5e, 0x5f, 0x59,
+               0x9f, 0x93, 0x91, 0x9d, 0x98, 0x94, 0x9e, 0x97,
+               0x96, 0x9f, 0x9b, 0x92, 0x93, 0x98, 0x94, 0x9e,
+               0x99, 0x9c, 0x97, 0x90, 0x92, 0x91, 0x9d, 0x9a,
+               0x9c, 0x96, 0x90, 0x99, 0x95, 0x9b, 0x9a, 0x95,
+               0x90, 0x9d, 0x9e, 0x98, 0x97, 0x9a, 0x9b, 0x91,
+               0x9a, 0x93, 0x94, 0x9f, 0x9d, 0x94, 0x91, 0x92,
+               0x95, 0x9b, 0x98, 0x96, 0x9c, 0x97, 0x96, 0x9c,
+               0x99, 0x90, 0x93, 0x95, 0x92, 0x9e, 0x9f, 0x99,
+               0x9f, 0x93, 0x91, 0x9d, 0x98, 0x94, 0x9e, 0x97,
+               0x96, 0x9f, 0x9b, 0x92, 0x93, 0x98, 0x94, 0x9e,
+               0x99, 0x9c, 0x97, 0x90, 0x92, 0x91, 0x9d, 0x9a,
+               0x9c, 0x96, 0x90, 0x99, 0x95, 0x9b, 0x9a, 0x95,
+               0x90, 0x9d, 0x9e, 0x98, 0x97, 0x9a, 0x9b, 0x91,
+               0x9a, 0x93, 0x94, 0x9f, 0x9d, 0x94, 0x91, 0x92,
+               0x95, 0x9b, 0x98, 0x96, 0x9c, 0x97, 0x96, 0x9c,
+               0x99, 0x90, 0x93, 0x95, 0x92, 0x9e, 0x9f, 0x99,
+               0x5f, 0x53, 0x51, 0x5d, 0x58, 0x54, 0x5e, 0x57,
+               0x56, 0x5f, 0x5b, 0x52, 0x53, 0x58, 0x54, 0x5e,
+               0x59, 0x5c, 0x57, 0x50, 0x52, 0x51, 0x5d, 0x5a,
+               0x5c, 0x56, 0x50, 0x59, 0x55, 0x5b, 0x5a, 0x55,
+               0x50, 0x5d, 0x5e, 0x58, 0x57, 0x5a, 0x5b, 0x51,
+               0x5a, 0x53, 0x54, 0x5f, 0x5d, 0x54, 0x51, 0x52,
+               0x55, 0x5b, 0x58, 0x56, 0x5c, 0x57, 0x56, 0x5c,
+               0x59, 0x50, 0x53, 0x55, 0x52, 0x5e, 0x5f, 0x59,
+               0x0f, 0x03, 0x01, 0x0d, 0x08, 0x04, 0x0e, 0x07,
+               0x06, 0x0f, 0x0b, 0x02, 0x03, 0x08, 0x04, 0x0e,
+               0x09, 0x0c, 0x07, 0x00, 0x02, 0x01, 0x0d, 0x0a,
+               0x0c, 0x06, 0x00, 0x09, 0x05, 0x0b, 0x0a, 0x05,
+               0x00, 0x0d, 0x0e, 0x08, 0x07, 0x0a, 0x0b, 0x01,
+               0x0a, 0x03, 0x04, 0x0f, 0x0d, 0x04, 0x01, 0x02,
+               0x05, 0x0b, 0x08, 0x06, 0x0c, 0x07, 0x06, 0x0c,
+               0x09, 0x00, 0x03, 0x05, 0x02, 0x0e, 0x0f, 0x09,
+               0x3f, 0x33, 0x31, 0x3d, 0x38, 0x34, 0x3e, 0x37,
+               0x36, 0x3f, 0x3b, 0x32, 0x33, 0x38, 0x34, 0x3e,
+               0x39, 0x3c, 0x37, 0x30, 0x32, 0x31, 0x3d, 0x3a,
+               0x3c, 0x36, 0x30, 0x39, 0x35, 0x3b, 0x3a, 0x35,
+               0x30, 0x3d, 0x3e, 0x38, 0x37, 0x3a, 0x3b, 0x31,
+               0x3a, 0x33, 0x34, 0x3f, 0x3d, 0x34, 0x31, 0x32,
+               0x35, 0x3b, 0x38, 0x36, 0x3c, 0x37, 0x36, 0x3c,
+               0x39, 0x30, 0x33, 0x35, 0x32, 0x3e, 0x3f, 0x39,
+               0x7f, 0x73, 0x71, 0x7d, 0x78, 0x74, 0x7e, 0x77,
+               0x76, 0x7f, 0x7b, 0x72, 0x73, 0x78, 0x74, 0x7e,
+               0x79, 0x7c, 0x77, 0x70, 0x72, 0x71, 0x7d, 0x7a,
+               0x7c, 0x76, 0x70, 0x79, 0x75, 0x7b, 0x7a, 0x75,
+               0x70, 0x7d, 0x7e, 0x78, 0x77, 0x7a, 0x7b, 0x71,
+               0x7a, 0x73, 0x74, 0x7f, 0x7d, 0x74, 0x71, 0x72,
+               0x75, 0x7b, 0x78, 0x76, 0x7c, 0x77, 0x76, 0x7c,
+               0x79, 0x70, 0x73, 0x75, 0x72, 0x7e, 0x7f, 0x79,
+               0x8f, 0x83, 0x81, 0x8d, 0x88, 0x84, 0x8e, 0x87,
+               0x86, 0x8f, 0x8b, 0x82, 0x83, 0x88, 0x84, 0x8e,
+               0x89, 0x8c, 0x87, 0x80, 0x82, 0x81, 0x8d, 0x8a,
+               0x8c, 0x86, 0x80, 0x89, 0x85, 0x8b, 0x8a, 0x85,
+               0x80, 0x8d, 0x8e, 0x88, 0x87, 0x8a, 0x8b, 0x81,
+               0x8a, 0x83, 0x84, 0x8f, 0x8d, 0x84, 0x81, 0x82,
+               0x85, 0x8b, 0x88, 0x86, 0x8c, 0x87, 0x86, 0x8c,
+               0x89, 0x80, 0x83, 0x85, 0x82, 0x8e, 0x8f, 0x89,
+               0x4f, 0x43, 0x41, 0x4d, 0x48, 0x44, 0x4e, 0x47,
+               0x46, 0x4f, 0x4b, 0x42, 0x43, 0x48, 0x44, 0x4e,
+               0x49, 0x4c, 0x47, 0x40, 0x42, 0x41, 0x4d, 0x4a,
+               0x4c, 0x46, 0x40, 0x49, 0x45, 0x4b, 0x4a, 0x45,
+               0x40, 0x4d, 0x4e, 0x48, 0x47, 0x4a, 0x4b, 0x41,
+               0x4a, 0x43, 0x44, 0x4f, 0x4d, 0x44, 0x41, 0x42,
+               0x45, 0x4b, 0x48, 0x46, 0x4c, 0x47, 0x46, 0x4c,
+               0x49, 0x40, 0x43, 0x45, 0x42, 0x4e, 0x4f, 0x49,
+               0xff, 0xf3, 0xf1, 0xfd, 0xf8, 0xf4, 0xfe, 0xf7,
+               0xf6, 0xff, 0xfb, 0xf2, 0xf3, 0xf8, 0xf4, 0xfe,
+               0xf9, 0xfc, 0xf7, 0xf0, 0xf2, 0xf1, 0xfd, 0xfa,
+               0xfc, 0xf6, 0xf0, 0xf9, 0xf5, 0xfb, 0xfa, 0xf5,
+               0xf0, 0xfd, 0xfe, 0xf8, 0xf7, 0xfa, 0xfb, 0xf1,
+               0xfa, 0xf3, 0xf4, 0xff, 0xfd, 0xf4, 0xf1, 0xf2,
+               0xf5, 0xfb, 0xf8, 0xf6, 0xfc, 0xf7, 0xf6, 0xfc,
+               0xf9, 0xf0, 0xf3, 0xf5, 0xf2, 0xfe, 0xff, 0xf9,
+               0x1f, 0x13, 0x11, 0x1d, 0x18, 0x14, 0x1e, 0x17,
+               0x16, 0x1f, 0x1b, 0x12, 0x13, 0x18, 0x14, 0x1e,
+               0x19, 0x1c, 0x17, 0x10, 0x12, 0x11, 0x1d, 0x1a,
+               0x1c, 0x16, 0x10, 0x19, 0x15, 0x1b, 0x1a, 0x15,
+               0x10, 0x1d, 0x1e, 0x18, 0x17, 0x1a, 0x1b, 0x11,
+               0x1a, 0x13, 0x14, 0x1f, 0x1d, 0x14, 0x11, 0x12,
+               0x15, 0x1b, 0x18, 0x16, 0x1c, 0x17, 0x16, 0x1c,
+               0x19, 0x10, 0x13, 0x15, 0x12, 0x1e, 0x1f, 0x19,
+               0xcf, 0xc3, 0xc1, 0xcd, 0xc8, 0xc4, 0xce, 0xc7,
+               0xc6, 0xcf, 0xcb, 0xc2, 0xc3, 0xc8, 0xc4, 0xce,
+               0xc9, 0xcc, 0xc7, 0xc0, 0xc2, 0xc1, 0xcd, 0xca,
+               0xcc, 0xc6, 0xc0, 0xc9, 0xc5, 0xcb, 0xca, 0xc5,
+               0xc0, 0xcd, 0xce, 0xc8, 0xc7, 0xca, 0xcb, 0xc1,
+               0xca, 0xc3, 0xc4, 0xcf, 0xcd, 0xc4, 0xc1, 0xc2,
+               0xc5, 0xcb, 0xc8, 0xc6, 0xcc, 0xc7, 0xc6, 0xcc,
+               0xc9, 0xc0, 0xc3, 0xc5, 0xc2, 0xce, 0xcf, 0xc9,
+               0xef, 0xe3, 0xe1, 0xed, 0xe8, 0xe4, 0xee, 0xe7,
+               0xe6, 0xef, 0xeb, 0xe2, 0xe3, 0xe8, 0xe4, 0xee,
+               0xe9, 0xec, 0xe7, 0xe0, 0xe2, 0xe1, 0xed, 0xea,
+               0xec, 0xe6, 0xe0, 0xe9, 0xe5, 0xeb, 0xea, 0xe5,
+               0xe0, 0xed, 0xee, 0xe8, 0xe7, 0xea, 0xeb, 0xe1,
+               0xea, 0xe3, 0xe4, 0xef, 0xed, 0xe4, 0xe1, 0xe2,
+               0xe5, 0xeb, 0xe8, 0xe6, 0xec, 0xe7, 0xe6, 0xec,
+               0xe9, 0xe0, 0xe3, 0xe5, 0xe2, 0xee, 0xef, 0xe9,
+               0x8f, 0x83, 0x81, 0x8d, 0x88, 0x84, 0x8e, 0x87,
+               0x86, 0x8f, 0x8b, 0x82, 0x83, 0x88, 0x84, 0x8e,
+               0x89, 0x8c, 0x87, 0x80, 0x82, 0x81, 0x8d, 0x8a,
+               0x8c, 0x86, 0x80, 0x89, 0x85, 0x8b, 0x8a, 0x85,
+               0x80, 0x8d, 0x8e, 0x88, 0x87, 0x8a, 0x8b, 0x81,
+               0x8a, 0x83, 0x84, 0x8f, 0x8d, 0x84, 0x81, 0x82,
+               0x85, 0x8b, 0x88, 0x86, 0x8c, 0x87, 0x86, 0x8c,
+               0x89, 0x80, 0x83, 0x85, 0x82, 0x8e, 0x8f, 0x89,
+               0x8f, 0x83, 0x81, 0x8d, 0x88, 0x84, 0x8e, 0x87,
+               0x86, 0x8f, 0x8b, 0x82, 0x83, 0x88, 0x84, 0x8e,
+               0x89, 0x8c, 0x87, 0x80, 0x82, 0x81, 0x8d, 0x8a,
+               0x8c, 0x86, 0x80, 0x89, 0x85, 0x8b, 0x8a, 0x85,
+               0x80, 0x8d, 0x8e, 0x88, 0x87, 0x8a, 0x8b, 0x81,
+               0x8a, 0x83, 0x84, 0x8f, 0x8d, 0x84, 0x81, 0x82,
+               0x85, 0x8b, 0x88, 0x86, 0x8c, 0x87, 0x86, 0x8c,
+               0x89, 0x80, 0x83, 0x85, 0x82, 0x8e, 0x8f, 0x89,
+               0x2f, 0x23, 0x21, 0x2d, 0x28, 0x24, 0x2e, 0x27,
+               0x26, 0x2f, 0x2b, 0x22, 0x23, 0x28, 0x24, 0x2e,
+               0x29, 0x2c, 0x27, 0x20, 0x22, 0x21, 0x2d, 0x2a,
+               0x2c, 0x26, 0x20, 0x29, 0x25, 0x2b, 0x2a, 0x25,
+               0x20, 0x2d, 0x2e, 0x28, 0x27, 0x2a, 0x2b, 0x21,
+               0x2a, 0x23, 0x24, 0x2f, 0x2d, 0x24, 0x21, 0x22,
+               0x25, 0x2b, 0x28, 0x26, 0x2c, 0x27, 0x26, 0x2c,
+               0x29, 0x20, 0x23, 0x25, 0x22, 0x2e, 0x2f, 0x29,
+               0xdf, 0xd3, 0xd1, 0xdd, 0xd8, 0xd4, 0xde, 0xd7,
+               0xd6, 0xdf, 0xdb, 0xd2, 0xd3, 0xd8, 0xd4, 0xde,
+               0xd9, 0xdc, 0xd7, 0xd0, 0xd2, 0xd1, 0xdd, 0xda,
+               0xdc, 0xd6, 0xd0, 0xd9, 0xd5, 0xdb, 0xda, 0xd5,
+               0xd0, 0xdd, 0xde, 0xd8, 0xd7, 0xda, 0xdb, 0xd1,
+               0xda, 0xd3, 0xd4, 0xdf, 0xdd, 0xd4, 0xd1, 0xd2,
+               0xd5, 0xdb, 0xd8, 0xd6, 0xdc, 0xd7, 0xd6, 0xdc,
+               0xd9, 0xd0, 0xd3, 0xd5, 0xd2, 0xde, 0xdf, 0xd9,
+               0x4f, 0x43, 0x41, 0x4d, 0x48, 0x44, 0x4e, 0x47,
+               0x46, 0x4f, 0x4b, 0x42, 0x43, 0x48, 0x44, 0x4e,
+               0x49, 0x4c, 0x47, 0x40, 0x42, 0x41, 0x4d, 0x4a,
+               0x4c, 0x46, 0x40, 0x49, 0x45, 0x4b, 0x4a, 0x45,
+               0x40, 0x4d, 0x4e, 0x48, 0x47, 0x4a, 0x4b, 0x41,
+               0x4a, 0x43, 0x44, 0x4f, 0x4d, 0x44, 0x41, 0x42,
+               0x45, 0x4b, 0x48, 0x46, 0x4c, 0x47, 0x46, 0x4c,
+               0x49, 0x40, 0x43, 0x45, 0x42, 0x4e, 0x4f, 0x49,
+               0x6f, 0x63, 0x61, 0x6d, 0x68, 0x64, 0x6e, 0x67,
+               0x66, 0x6f, 0x6b, 0x62, 0x63, 0x68, 0x64, 0x6e,
+               0x69, 0x6c, 0x67, 0x60, 0x62, 0x61, 0x6d, 0x6a,
+               0x6c, 0x66, 0x60, 0x69, 0x65, 0x6b, 0x6a, 0x65,
+               0x60, 0x6d, 0x6e, 0x68, 0x67, 0x6a, 0x6b, 0x61,
+               0x6a, 0x63, 0x64, 0x6f, 0x6d, 0x64, 0x61, 0x62,
+               0x65, 0x6b, 0x68, 0x66, 0x6c, 0x67, 0x66, 0x6c,
+               0x69, 0x60, 0x63, 0x65, 0x62, 0x6e, 0x6f, 0x69,
+               0x9f, 0x93, 0x91, 0x9d, 0x98, 0x94, 0x9e, 0x97,
+               0x96, 0x9f, 0x9b, 0x92, 0x93, 0x98, 0x94, 0x9e,
+               0x99, 0x9c, 0x97, 0x90, 0x92, 0x91, 0x9d, 0x9a,
+               0x9c, 0x96, 0x90, 0x99, 0x95, 0x9b, 0x9a, 0x95,
+               0x90, 0x9d, 0x9e, 0x98, 0x97, 0x9a, 0x9b, 0x91,
+               0x9a, 0x93, 0x94, 0x9f, 0x9d, 0x94, 0x91, 0x92,
+               0x95, 0x9b, 0x98, 0x96, 0x9c, 0x97, 0x96, 0x9c,
+               0x99, 0x90, 0x93, 0x95, 0x92, 0x9e, 0x9f, 0x99,
+               0x2f, 0x23, 0x21, 0x2d, 0x28, 0x24, 0x2e, 0x27,
+               0x26, 0x2f, 0x2b, 0x22, 0x23, 0x28, 0x24, 0x2e,
+               0x29, 0x2c, 0x27, 0x20, 0x22, 0x21, 0x2d, 0x2a,
+               0x2c, 0x26, 0x20, 0x29, 0x25, 0x2b, 0x2a, 0x25,
+               0x20, 0x2d, 0x2e, 0x28, 0x27, 0x2a, 0x2b, 0x21,
+               0x2a, 0x23, 0x24, 0x2f, 0x2d, 0x24, 0x21, 0x22,
+               0x25, 0x2b, 0x28, 0x26, 0x2c, 0x27, 0x26, 0x2c,
+               0x29, 0x20, 0x23, 0x25, 0x22, 0x2e, 0x2f, 0x29,
+               0x1f, 0x13, 0x11, 0x1d, 0x18, 0x14, 0x1e, 0x17,
+               0x16, 0x1f, 0x1b, 0x12, 0x13, 0x18, 0x14, 0x1e,
+               0x19, 0x1c, 0x17, 0x10, 0x12, 0x11, 0x1d, 0x1a,
+               0x1c, 0x16, 0x10, 0x19, 0x15, 0x1b, 0x1a, 0x15,
+               0x10, 0x1d, 0x1e, 0x18, 0x17, 0x1a, 0x1b, 0x11,
+               0x1a, 0x13, 0x14, 0x1f, 0x1d, 0x14, 0x11, 0x12,
+               0x15, 0x1b, 0x18, 0x16, 0x1c, 0x17, 0x16, 0x1c,
+               0x19, 0x10, 0x13, 0x15, 0x12, 0x1e, 0x1f, 0x19,
+               0xbf, 0xb3, 0xb1, 0xbd, 0xb8, 0xb4, 0xbe, 0xb7,
+               0xb6, 0xbf, 0xbb, 0xb2, 0xb3, 0xb8, 0xb4, 0xbe,
+               0xb9, 0xbc, 0xb7, 0xb0, 0xb2, 0xb1, 0xbd, 0xba,
+               0xbc, 0xb6, 0xb0, 0xb9, 0xb5, 0xbb, 0xba, 0xb5,
+               0xb0, 0xbd, 0xbe, 0xb8, 0xb7, 0xba, 0xbb, 0xb1,
+               0xba, 0xb3, 0xb4, 0xbf, 0xbd, 0xb4, 0xb1, 0xb2,
+               0xb5, 0xbb, 0xb8, 0xb6, 0xbc, 0xb7, 0xb6, 0xbc,
+               0xb9, 0xb0, 0xb3, 0xb5, 0xb2, 0xbe, 0xbf, 0xb9,
+               0x7f, 0x73, 0x71, 0x7d, 0x78, 0x74, 0x7e, 0x77,
+               0x76, 0x7f, 0x7b, 0x72, 0x73, 0x78, 0x74, 0x7e,
+               0x79, 0x7c, 0x77, 0x70, 0x72, 0x71, 0x7d, 0x7a,
+               0x7c, 0x76, 0x70, 0x79, 0x75, 0x7b, 0x7a, 0x75,
+               0x70, 0x7d, 0x7e, 0x78, 0x77, 0x7a, 0x7b, 0x71,
+               0x7a, 0x73, 0x74, 0x7f, 0x7d, 0x74, 0x71, 0x72,
+               0x75, 0x7b, 0x78, 0x76, 0x7c, 0x77, 0x76, 0x7c,
+               0x79, 0x70, 0x73, 0x75, 0x72, 0x7e, 0x7f, 0x79,
+               0xff, 0xf3, 0xf1, 0xfd, 0xf8, 0xf4, 0xfe, 0xf7,
+               0xf6, 0xff, 0xfb, 0xf2, 0xf3, 0xf8, 0xf4, 0xfe,
+               0xf9, 0xfc, 0xf7, 0xf0, 0xf2, 0xf1, 0xfd, 0xfa,
+               0xfc, 0xf6, 0xf0, 0xf9, 0xf5, 0xfb, 0xfa, 0xf5,
+               0xf0, 0xfd, 0xfe, 0xf8, 0xf7, 0xfa, 0xfb, 0xf1,
+               0xfa, 0xf3, 0xf4, 0xff, 0xfd, 0xf4, 0xf1, 0xf2,
+               0xf5, 0xfb, 0xf8, 0xf6, 0xfc, 0xf7, 0xf6, 0xfc,
+               0xf9, 0xf0, 0xf3, 0xf5, 0xf2, 0xfe, 0xff, 0xf9,
+               0x5f, 0x53, 0x51, 0x5d, 0x58, 0x54, 0x5e, 0x57,
+               0x56, 0x5f, 0x5b, 0x52, 0x53, 0x58, 0x54, 0x5e,
+               0x59, 0x5c, 0x57, 0x50, 0x52, 0x51, 0x5d, 0x5a,
+               0x5c, 0x56, 0x50, 0x59, 0x55, 0x5b, 0x5a, 0x55,
+               0x50, 0x5d, 0x5e, 0x58, 0x57, 0x5a, 0x5b, 0x51,
+               0x5a, 0x53, 0x54, 0x5f, 0x5d, 0x54, 0x51, 0x52,
+               0x55, 0x5b, 0x58, 0x56, 0x5c, 0x57, 0x56, 0x5c,
+               0x59, 0x50, 0x53, 0x55, 0x52, 0x5e, 0x5f, 0x59,
+               0xcf, 0xc3, 0xc1, 0xcd, 0xc8, 0xc4, 0xce, 0xc7,
+               0xc6, 0xcf, 0xcb, 0xc2, 0xc3, 0xc8, 0xc4, 0xce,
+               0xc9, 0xcc, 0xc7, 0xc0, 0xc2, 0xc1, 0xcd, 0xca,
+               0xcc, 0xc6, 0xc0, 0xc9, 0xc5, 0xcb, 0xca, 0xc5,
+               0xc0, 0xcd, 0xce, 0xc8, 0xc7, 0xca, 0xcb, 0xc1,
+               0xca, 0xc3, 0xc4, 0xcf, 0xcd, 0xc4, 0xc1, 0xc2,
+               0xc5, 0xcb, 0xc8, 0xc6, 0xcc, 0xc7, 0xc6, 0xcc,
+               0xc9, 0xc0, 0xc3, 0xc5, 0xc2, 0xce, 0xcf, 0xc9,
+               0xbf, 0xb3, 0xb1, 0xbd, 0xb8, 0xb4, 0xbe, 0xb7,
+               0xb6, 0xbf, 0xbb, 0xb2, 0xb3, 0xb8, 0xb4, 0xbe,
+               0xb9, 0xbc, 0xb7, 0xb0, 0xb2, 0xb1, 0xbd, 0xba,
+               0xbc, 0xb6, 0xb0, 0xb9, 0xb5, 0xbb, 0xba, 0xb5,
+               0xb0, 0xbd, 0xbe, 0xb8, 0xb7, 0xba, 0xbb, 0xb1,
+               0xba, 0xb3, 0xb4, 0xbf, 0xbd, 0xb4, 0xb1, 0xb2,
+               0xb5, 0xbb, 0xb8, 0xb6, 0xbc, 0xb7, 0xb6, 0xbc,
+               0xb9, 0xb0, 0xb3, 0xb5, 0xb2, 0xbe, 0xbf, 0xb9,
+               0x9f, 0x93, 0x91, 0x9d, 0x98, 0x94, 0x9e, 0x97,
+               0x96, 0x9f, 0x9b, 0x92, 0x93, 0x98, 0x94, 0x9e,
+               0x99, 0x9c, 0x97, 0x90, 0x92, 0x91, 0x9d, 0x9a,
+               0x9c, 0x96, 0x90, 0x99, 0x95, 0x9b, 0x9a, 0x95,
+               0x90, 0x9d, 0x9e, 0x98, 0x97, 0x9a, 0x9b, 0x91,
+               0x9a, 0x93, 0x94, 0x9f, 0x9d, 0x94, 0x91, 0x92,
+               0x95, 0x9b, 0x98, 0x96, 0x9c, 0x97, 0x96, 0x9c,
+               0x99, 0x90, 0x93, 0x95, 0x92, 0x9e, 0x9f, 0x99,
+               0x3f, 0x33, 0x31, 0x3d, 0x38, 0x34, 0x3e, 0x37,
+               0x36, 0x3f, 0x3b, 0x32, 0x33, 0x38, 0x34, 0x3e,
+               0x39, 0x3c, 0x37, 0x30, 0x32, 0x31, 0x3d, 0x3a,
+               0x3c, 0x36, 0x30, 0x39, 0x35, 0x3b, 0x3a, 0x35,
+               0x30, 0x3d, 0x3e, 0x38, 0x37, 0x3a, 0x3b, 0x31,
+               0x3a, 0x33, 0x34, 0x3f, 0x3d, 0x34, 0x31, 0x32,
+               0x35, 0x3b, 0x38, 0x36, 0x3c, 0x37, 0x36, 0x3c,
+               0x39, 0x30, 0x33, 0x35, 0x32, 0x3e, 0x3f, 0x39,
+               0x7f, 0x73, 0x71, 0x7d, 0x78, 0x74, 0x7e, 0x77,
+               0x76, 0x7f, 0x7b, 0x72, 0x73, 0x78, 0x74, 0x7e,
+               0x79, 0x7c, 0x77, 0x70, 0x72, 0x71, 0x7d, 0x7a,
+               0x7c, 0x76, 0x70, 0x79, 0x75, 0x7b, 0x7a, 0x75,
+               0x70, 0x7d, 0x7e, 0x78, 0x77, 0x7a, 0x7b, 0x71,
+               0x7a, 0x73, 0x74, 0x7f, 0x7d, 0x74, 0x71, 0x72,
+               0x75, 0x7b, 0x78, 0x76, 0x7c, 0x77, 0x76, 0x7c,
+               0x79, 0x70, 0x73, 0x75, 0x72, 0x7e, 0x7f, 0x79,
+               0xef, 0xe3, 0xe1, 0xed, 0xe8, 0xe4, 0xee, 0xe7,
+               0xe6, 0xef, 0xeb, 0xe2, 0xe3, 0xe8, 0xe4, 0xee,
+               0xe9, 0xec, 0xe7, 0xe0, 0xe2, 0xe1, 0xed, 0xea,
+               0xec, 0xe6, 0xe0, 0xe9, 0xe5, 0xeb, 0xea, 0xe5,
+               0xe0, 0xed, 0xee, 0xe8, 0xe7, 0xea, 0xeb, 0xe1,
+               0xea, 0xe3, 0xe4, 0xef, 0xed, 0xe4, 0xe1, 0xe2,
+               0xe5, 0xeb, 0xe8, 0xe6, 0xec, 0xe7, 0xe6, 0xec,
+               0xe9, 0xe0, 0xe3, 0xe5, 0xe2, 0xee, 0xef, 0xe9,
+               0x3f, 0x33, 0x31, 0x3d, 0x38, 0x34, 0x3e, 0x37,
+               0x36, 0x3f, 0x3b, 0x32, 0x33, 0x38, 0x34, 0x3e,
+               0x39, 0x3c, 0x37, 0x30, 0x32, 0x31, 0x3d, 0x3a,
+               0x3c, 0x36, 0x30, 0x39, 0x35, 0x3b, 0x3a, 0x35,
+               0x30, 0x3d, 0x3e, 0x38, 0x37, 0x3a, 0x3b, 0x31,
+               0x3a, 0x33, 0x34, 0x3f, 0x3d, 0x34, 0x31, 0x32,
+               0x35, 0x3b, 0x38, 0x36, 0x3c, 0x37, 0x36, 0x3c,
+               0x39, 0x30, 0x33, 0x35, 0x32, 0x3e, 0x3f, 0x39,
+               0xaf, 0xa3, 0xa1, 0xad, 0xa8, 0xa4, 0xae, 0xa7,
+               0xa6, 0xaf, 0xab, 0xa2, 0xa3, 0xa8, 0xa4, 0xae,
+               0xa9, 0xac, 0xa7, 0xa0, 0xa2, 0xa1, 0xad, 0xaa,
+               0xac, 0xa6, 0xa0, 0xa9, 0xa5, 0xab, 0xaa, 0xa5,
+               0xa0, 0xad, 0xae, 0xa8, 0xa7, 0xaa, 0xab, 0xa1,
+               0xaa, 0xa3, 0xa4, 0xaf, 0xad, 0xa4, 0xa1, 0xa2,
+               0xa5, 0xab, 0xa8, 0xa6, 0xac, 0xa7, 0xa6, 0xac,
+               0xa9, 0xa0, 0xa3, 0xa5, 0xa2, 0xae, 0xaf, 0xa9,
+               0xaf, 0xa3, 0xa1, 0xad, 0xa8, 0xa4, 0xae, 0xa7,
+               0xa6, 0xaf, 0xab, 0xa2, 0xa3, 0xa8, 0xa4, 0xae,
+               0xa9, 0xac, 0xa7, 0xa0, 0xa2, 0xa1, 0xad, 0xaa,
+               0xac, 0xa6, 0xa0, 0xa9, 0xa5, 0xab, 0xaa, 0xa5,
+               0xa0, 0xad, 0xae, 0xa8, 0xa7, 0xaa, 0xab, 0xa1,
+               0xaa, 0xa3, 0xa4, 0xaf, 0xad, 0xa4, 0xa1, 0xa2,
+               0xa5, 0xab, 0xa8, 0xa6, 0xac, 0xa7, 0xa6, 0xac,
+               0xa9, 0xa0, 0xa3, 0xa5, 0xa2, 0xae, 0xaf, 0xa9,
+               0x0f, 0x03, 0x01, 0x0d, 0x08, 0x04, 0x0e, 0x07,
+               0x06, 0x0f, 0x0b, 0x02, 0x03, 0x08, 0x04, 0x0e,
+               0x09, 0x0c, 0x07, 0x00, 0x02, 0x01, 0x0d, 0x0a,
+               0x0c, 0x06, 0x00, 0x09, 0x05, 0x0b, 0x0a, 0x05,
+               0x00, 0x0d, 0x0e, 0x08, 0x07, 0x0a, 0x0b, 0x01,
+               0x0a, 0x03, 0x04, 0x0f, 0x0d, 0x04, 0x01, 0x02,
+               0x05, 0x0b, 0x08, 0x06, 0x0c, 0x07, 0x06, 0x0c,
+               0x09, 0x00, 0x03, 0x05, 0x02, 0x0e, 0x0f, 0x09,
+               0x5f, 0x53, 0x51, 0x5d, 0x58, 0x54, 0x5e, 0x57,
+               0x56, 0x5f, 0x5b, 0x52, 0x53, 0x58, 0x54, 0x5e,
+               0x59, 0x5c, 0x57, 0x50, 0x52, 0x51, 0x5d, 0x5a,
+               0x5c, 0x56, 0x50, 0x59, 0x55, 0x5b, 0x5a, 0x55,
+               0x50, 0x5d, 0x5e, 0x58, 0x57, 0x5a, 0x5b, 0x51,
+               0x5a, 0x53, 0x54, 0x5f, 0x5d, 0x54, 0x51, 0x52,
+               0x55, 0x5b, 0x58, 0x56, 0x5c, 0x57, 0x56, 0x5c,
+               0x59, 0x50, 0x53, 0x55, 0x52, 0x5e, 0x5f, 0x59,
+               0x6f, 0x63, 0x61, 0x6d, 0x68, 0x64, 0x6e, 0x67,
+               0x66, 0x6f, 0x6b, 0x62, 0x63, 0x68, 0x64, 0x6e,
+               0x69, 0x6c, 0x67, 0x60, 0x62, 0x61, 0x6d, 0x6a,
+               0x6c, 0x66, 0x60, 0x69, 0x65, 0x6b, 0x6a, 0x65,
+               0x60, 0x6d, 0x6e, 0x68, 0x67, 0x6a, 0x6b, 0x61,
+               0x6a, 0x63, 0x64, 0x6f, 0x6d, 0x64, 0x61, 0x62,
+               0x65, 0x6b, 0x68, 0x66, 0x6c, 0x67, 0x66, 0x6c,
+               0x69, 0x60, 0x63, 0x65, 0x62, 0x6e, 0x6f, 0x69,
+               0x0f, 0x03, 0x01, 0x0d, 0x08, 0x04, 0x0e, 0x07,
+               0x06, 0x0f, 0x0b, 0x02, 0x03, 0x08, 0x04, 0x0e,
+               0x09, 0x0c, 0x07, 0x00, 0x02, 0x01, 0x0d, 0x0a,
+               0x0c, 0x06, 0x00, 0x09, 0x05, 0x0b, 0x0a, 0x05,
+               0x00, 0x0d, 0x0e, 0x08, 0x07, 0x0a, 0x0b, 0x01,
+               0x0a, 0x03, 0x04, 0x0f, 0x0d, 0x04, 0x01, 0x02,
+               0x05, 0x0b, 0x08, 0x06, 0x0c, 0x07, 0x06, 0x0c,
+               0x09, 0x00, 0x03, 0x05, 0x02, 0x0e, 0x0f, 0x09,
+               0xdf, 0xd3, 0xd1, 0xdd, 0xd8, 0xd4, 0xde, 0xd7,
+               0xd6, 0xdf, 0xdb, 0xd2, 0xd3, 0xd8, 0xd4, 0xde,
+               0xd9, 0xdc, 0xd7, 0xd0, 0xd2, 0xd1, 0xdd, 0xda,
+               0xdc, 0xd6, 0xd0, 0xd9, 0xd5, 0xdb, 0xda, 0xd5,
+               0xd0, 0xdd, 0xde, 0xd8, 0xd7, 0xda, 0xdb, 0xd1,
+               0xda, 0xd3, 0xd4, 0xdf, 0xdd, 0xd4, 0xd1, 0xd2,
+               0xd5, 0xdb, 0xd8, 0xd6, 0xdc, 0xd7, 0xd6, 0xdc,
+               0xd9, 0xd0, 0xd3, 0xd5, 0xd2, 0xde, 0xdf, 0xd9,
+       },{
+               0xa7, 0xad, 0xad, 0xa8, 0xae, 0xab, 0xa3, 0xa5,
+               0xa0, 0xa6, 0xa6, 0xaf, 0xa9, 0xa0, 0xaa, 0xa3,
+               0xa1, 0xa4, 0xa2, 0xa7, 0xa8, 0xa2, 0xa5, 0xac,
+               0xab, 0xa1, 0xac, 0xaa, 0xa4, 0xae, 0xaf, 0xa9,
+               0xaa, 0xa3, 0xa6, 0xaf, 0xa9, 0xa0, 0xa0, 0xa6,
+               0xac, 0xaa, 0xab, 0xa1, 0xa7, 0xad, 0xad, 0xa8,
+               0xaf, 0xa9, 0xa1, 0xa4, 0xa3, 0xa5, 0xae, 0xab,
+               0xa5, 0xac, 0xa2, 0xa7, 0xa8, 0xa2, 0xa4, 0xae,
+               0xd7, 0xdd, 0xdd, 0xd8, 0xde, 0xdb, 0xd3, 0xd5,
+               0xd0, 0xd6, 0xd6, 0xdf, 0xd9, 0xd0, 0xda, 0xd3,
+               0xd1, 0xd4, 0xd2, 0xd7, 0xd8, 0xd2, 0xd5, 0xdc,
+               0xdb, 0xd1, 0xdc, 0xda, 0xd4, 0xde, 0xdf, 0xd9,
+               0xda, 0xd3, 0xd6, 0xdf, 0xd9, 0xd0, 0xd0, 0xd6,
+               0xdc, 0xda, 0xdb, 0xd1, 0xd7, 0xdd, 0xdd, 0xd8,
+               0xdf, 0xd9, 0xd1, 0xd4, 0xd3, 0xd5, 0xde, 0xdb,
+               0xd5, 0xdc, 0xd2, 0xd7, 0xd8, 0xd2, 0xd4, 0xde,
+               0x07, 0x0d, 0x0d, 0x08, 0x0e, 0x0b, 0x03, 0x05,
+               0x00, 0x06, 0x06, 0x0f, 0x09, 0x00, 0x0a, 0x03,
+               0x01, 0x04, 0x02, 0x07, 0x08, 0x02, 0x05, 0x0c,
+               0x0b, 0x01, 0x0c, 0x0a, 0x04, 0x0e, 0x0f, 0x09,
+               0x0a, 0x03, 0x06, 0x0f, 0x09, 0x00, 0x00, 0x06,
+               0x0c, 0x0a, 0x0b, 0x01, 0x07, 0x0d, 0x0d, 0x08,
+               0x0f, 0x09, 0x01, 0x04, 0x03, 0x05, 0x0e, 0x0b,
+               0x05, 0x0c, 0x02, 0x07, 0x08, 0x02, 0x04, 0x0e,
+               0x77, 0x7d, 0x7d, 0x78, 0x7e, 0x7b, 0x73, 0x75,
+               0x70, 0x76, 0x76, 0x7f, 0x79, 0x70, 0x7a, 0x73,
+               0x71, 0x74, 0x72, 0x77, 0x78, 0x72, 0x75, 0x7c,
+               0x7b, 0x71, 0x7c, 0x7a, 0x74, 0x7e, 0x7f, 0x79,
+               0x7a, 0x73, 0x76, 0x7f, 0x79, 0x70, 0x70, 0x76,
+               0x7c, 0x7a, 0x7b, 0x71, 0x77, 0x7d, 0x7d, 0x78,
+               0x7f, 0x79, 0x71, 0x74, 0x73, 0x75, 0x7e, 0x7b,
+               0x75, 0x7c, 0x72, 0x77, 0x78, 0x72, 0x74, 0x7e,
+               0x97, 0x9d, 0x9d, 0x98, 0x9e, 0x9b, 0x93, 0x95,
+               0x90, 0x96, 0x96, 0x9f, 0x99, 0x90, 0x9a, 0x93,
+               0x91, 0x94, 0x92, 0x97, 0x98, 0x92, 0x95, 0x9c,
+               0x9b, 0x91, 0x9c, 0x9a, 0x94, 0x9e, 0x9f, 0x99,
+               0x9a, 0x93, 0x96, 0x9f, 0x99, 0x90, 0x90, 0x96,
+               0x9c, 0x9a, 0x9b, 0x91, 0x97, 0x9d, 0x9d, 0x98,
+               0x9f, 0x99, 0x91, 0x94, 0x93, 0x95, 0x9e, 0x9b,
+               0x95, 0x9c, 0x92, 0x97, 0x98, 0x92, 0x94, 0x9e,
+               0x07, 0x0d, 0x0d, 0x08, 0x0e, 0x0b, 0x03, 0x05,
+               0x00, 0x06, 0x06, 0x0f, 0x09, 0x00, 0x0a, 0x03,
+               0x01, 0x04, 0x02, 0x07, 0x08, 0x02, 0x05, 0x0c,
+               0x0b, 0x01, 0x0c, 0x0a, 0x04, 0x0e, 0x0f, 0x09,
+               0x0a, 0x03, 0x06, 0x0f, 0x09, 0x00, 0x00, 0x06,
+               0x0c, 0x0a, 0x0b, 0x01, 0x07, 0x0d, 0x0d, 0x08,
+               0x0f, 0x09, 0x01, 0x04, 0x03, 0x05, 0x0e, 0x0b,
+               0x05, 0x0c, 0x02, 0x07, 0x08, 0x02, 0x04, 0x0e,
+               0xe7, 0xed, 0xed, 0xe8, 0xee, 0xeb, 0xe3, 0xe5,
+               0xe0, 0xe6, 0xe6, 0xef, 0xe9, 0xe0, 0xea, 0xe3,
+               0xe1, 0xe4, 0xe2, 0xe7, 0xe8, 0xe2, 0xe5, 0xec,
+               0xeb, 0xe1, 0xec, 0xea, 0xe4, 0xee, 0xef, 0xe9,
+               0xea, 0xe3, 0xe6, 0xef, 0xe9, 0xe0, 0xe0, 0xe6,
+               0xec, 0xea, 0xeb, 0xe1, 0xe7, 0xed, 0xed, 0xe8,
+               0xef, 0xe9, 0xe1, 0xe4, 0xe3, 0xe5, 0xee, 0xeb,
+               0xe5, 0xec, 0xe2, 0xe7, 0xe8, 0xe2, 0xe4, 0xee,
+               0x97, 0x9d, 0x9d, 0x98, 0x9e, 0x9b, 0x93, 0x95,
+               0x90, 0x96, 0x96, 0x9f, 0x99, 0x90, 0x9a, 0x93,
+               0x91, 0x94, 0x92, 0x97, 0x98, 0x92, 0x95, 0x9c,
+               0x9b, 0x91, 0x9c, 0x9a, 0x94, 0x9e, 0x9f, 0x99,
+               0x9a, 0x93, 0x96, 0x9f, 0x99, 0x90, 0x90, 0x96,
+               0x9c, 0x9a, 0x9b, 0x91, 0x97, 0x9d, 0x9d, 0x98,
+               0x9f, 0x99, 0x91, 0x94, 0x93, 0x95, 0x9e, 0x9b,
+               0x95, 0x9c, 0x92, 0x97, 0x98, 0x92, 0x94, 0x9e,
+               0x67, 0x6d, 0x6d, 0x68, 0x6e, 0x6b, 0x63, 0x65,
+               0x60, 0x66, 0x66, 0x6f, 0x69, 0x60, 0x6a, 0x63,
+               0x61, 0x64, 0x62, 0x67, 0x68, 0x62, 0x65, 0x6c,
+               0x6b, 0x61, 0x6c, 0x6a, 0x64, 0x6e, 0x6f, 0x69,
+               0x6a, 0x63, 0x66, 0x6f, 0x69, 0x60, 0x60, 0x66,
+               0x6c, 0x6a, 0x6b, 0x61, 0x67, 0x6d, 0x6d, 0x68,
+               0x6f, 0x69, 0x61, 0x64, 0x63, 0x65, 0x6e, 0x6b,
+               0x65, 0x6c, 0x62, 0x67, 0x68, 0x62, 0x64, 0x6e,
+               0x37, 0x3d, 0x3d, 0x38, 0x3e, 0x3b, 0x33, 0x35,
+               0x30, 0x36, 0x36, 0x3f, 0x39, 0x30, 0x3a, 0x33,
+               0x31, 0x34, 0x32, 0x37, 0x38, 0x32, 0x35, 0x3c,
+               0x3b, 0x31, 0x3c, 0x3a, 0x34, 0x3e, 0x3f, 0x39,
+               0x3a, 0x33, 0x36, 0x3f, 0x39, 0x30, 0x30, 0x36,
+               0x3c, 0x3a, 0x3b, 0x31, 0x37, 0x3d, 0x3d, 0x38,
+               0x3f, 0x39, 0x31, 0x34, 0x33, 0x35, 0x3e, 0x3b,
+               0x35, 0x3c, 0x32, 0x37, 0x38, 0x32, 0x34, 0x3e,
+               0x37, 0x3d, 0x3d, 0x38, 0x3e, 0x3b, 0x33, 0x35,
+               0x30, 0x36, 0x36, 0x3f, 0x39, 0x30, 0x3a, 0x33,
+               0x31, 0x34, 0x32, 0x37, 0x38, 0x32, 0x35, 0x3c,
+               0x3b, 0x31, 0x3c, 0x3a, 0x34, 0x3e, 0x3f, 0x39,
+               0x3a, 0x33, 0x36, 0x3f, 0x39, 0x30, 0x30, 0x36,
+               0x3c, 0x3a, 0x3b, 0x31, 0x37, 0x3d, 0x3d, 0x38,
+               0x3f, 0x39, 0x31, 0x34, 0x33, 0x35, 0x3e, 0x3b,
+               0x35, 0x3c, 0x32, 0x37, 0x38, 0x32, 0x34, 0x3e,
+               0x47, 0x4d, 0x4d, 0x48, 0x4e, 0x4b, 0x43, 0x45,
+               0x40, 0x46, 0x46, 0x4f, 0x49, 0x40, 0x4a, 0x43,
+               0x41, 0x44, 0x42, 0x47, 0x48, 0x42, 0x45, 0x4c,
+               0x4b, 0x41, 0x4c, 0x4a, 0x44, 0x4e, 0x4f, 0x49,
+               0x4a, 0x43, 0x46, 0x4f, 0x49, 0x40, 0x40, 0x46,
+               0x4c, 0x4a, 0x4b, 0x41, 0x47, 0x4d, 0x4d, 0x48,
+               0x4f, 0x49, 0x41, 0x44, 0x43, 0x45, 0x4e, 0x4b,
+               0x45, 0x4c, 0x42, 0x47, 0x48, 0x42, 0x44, 0x4e,
+               0xf7, 0xfd, 0xfd, 0xf8, 0xfe, 0xfb, 0xf3, 0xf5,
+               0xf0, 0xf6, 0xf6, 0xff, 0xf9, 0xf0, 0xfa, 0xf3,
+               0xf1, 0xf4, 0xf2, 0xf7, 0xf8, 0xf2, 0xf5, 0xfc,
+               0xfb, 0xf1, 0xfc, 0xfa, 0xf4, 0xfe, 0xff, 0xf9,
+               0xfa, 0xf3, 0xf6, 0xff, 0xf9, 0xf0, 0xf0, 0xf6,
+               0xfc, 0xfa, 0xfb, 0xf1, 0xf7, 0xfd, 0xfd, 0xf8,
+               0xff, 0xf9, 0xf1, 0xf4, 0xf3, 0xf5, 0xfe, 0xfb,
+               0xf5, 0xfc, 0xf2, 0xf7, 0xf8, 0xf2, 0xf4, 0xfe,
+               0x67, 0x6d, 0x6d, 0x68, 0x6e, 0x6b, 0x63, 0x65,
+               0x60, 0x66, 0x66, 0x6f, 0x69, 0x60, 0x6a, 0x63,
+               0x61, 0x64, 0x62, 0x67, 0x68, 0x62, 0x65, 0x6c,
+               0x6b, 0x61, 0x6c, 0x6a, 0x64, 0x6e, 0x6f, 0x69,
+               0x6a, 0x63, 0x66, 0x6f, 0x69, 0x60, 0x60, 0x66,
+               0x6c, 0x6a, 0x6b, 0x61, 0x67, 0x6d, 0x6d, 0x68,
+               0x6f, 0x69, 0x61, 0x64, 0x63, 0x65, 0x6e, 0x6b,
+               0x65, 0x6c, 0x62, 0x67, 0x68, 0x62, 0x64, 0x6e,
+               0x57, 0x5d, 0x5d, 0x58, 0x5e, 0x5b, 0x53, 0x55,
+               0x50, 0x56, 0x56, 0x5f, 0x59, 0x50, 0x5a, 0x53,
+               0x51, 0x54, 0x52, 0x57, 0x58, 0x52, 0x55, 0x5c,
+               0x5b, 0x51, 0x5c, 0x5a, 0x54, 0x5e, 0x5f, 0x59,
+               0x5a, 0x53, 0x56, 0x5f, 0x59, 0x50, 0x50, 0x56,
+               0x5c, 0x5a, 0x5b, 0x51, 0x57, 0x5d, 0x5d, 0x58,
+               0x5f, 0x59, 0x51, 0x54, 0x53, 0x55, 0x5e, 0x5b,
+               0x55, 0x5c, 0x52, 0x57, 0x58, 0x52, 0x54, 0x5e,
+               0xa7, 0xad, 0xad, 0xa8, 0xae, 0xab, 0xa3, 0xa5,
+               0xa0, 0xa6, 0xa6, 0xaf, 0xa9, 0xa0, 0xaa, 0xa3,
+               0xa1, 0xa4, 0xa2, 0xa7, 0xa8, 0xa2, 0xa5, 0xac,
+               0xab, 0xa1, 0xac, 0xaa, 0xa4, 0xae, 0xaf, 0xa9,
+               0xaa, 0xa3, 0xa6, 0xaf, 0xa9, 0xa0, 0xa0, 0xa6,
+               0xac, 0xaa, 0xab, 0xa1, 0xa7, 0xad, 0xad, 0xa8,
+               0xaf, 0xa9, 0xa1, 0xa4, 0xa3, 0xa5, 0xae, 0xab,
+               0xa5, 0xac, 0xa2, 0xa7, 0xa8, 0xa2, 0xa4, 0xae,
+               0x17, 0x1d, 0x1d, 0x18, 0x1e, 0x1b, 0x13, 0x15,
+               0x10, 0x16, 0x16, 0x1f, 0x19, 0x10, 0x1a, 0x13,
+               0x11, 0x14, 0x12, 0x17, 0x18, 0x12, 0x15, 0x1c,
+               0x1b, 0x11, 0x1c, 0x1a, 0x14, 0x1e, 0x1f, 0x19,
+               0x1a, 0x13, 0x16, 0x1f, 0x19, 0x10, 0x10, 0x16,
+               0x1c, 0x1a, 0x1b, 0x11, 0x17, 0x1d, 0x1d, 0x18,
+               0x1f, 0x19, 0x11, 0x14, 0x13, 0x15, 0x1e, 0x1b,
+               0x15, 0x1c, 0x12, 0x17, 0x18, 0x12, 0x14, 0x1e,
+               0x27, 0x2d, 0x2d, 0x28, 0x2e, 0x2b, 0x23, 0x25,
+               0x20, 0x26, 0x26, 0x2f, 0x29, 0x20, 0x2a, 0x23,
+               0x21, 0x24, 0x22, 0x27, 0x28, 0x22, 0x25, 0x2c,
+               0x2b, 0x21, 0x2c, 0x2a, 0x24, 0x2e, 0x2f, 0x29,
+               0x2a, 0x23, 0x26, 0x2f, 0x29, 0x20, 0x20, 0x26,
+               0x2c, 0x2a, 0x2b, 0x21, 0x27, 0x2d, 0x2d, 0x28,
+               0x2f, 0x29, 0x21, 0x24, 0x23, 0x25, 0x2e, 0x2b,
+               0x25, 0x2c, 0x22, 0x27, 0x28, 0x22, 0x24, 0x2e,
+               0xd7, 0xdd, 0xdd, 0xd8, 0xde, 0xdb, 0xd3, 0xd5,
+               0xd0, 0xd6, 0xd6, 0xdf, 0xd9, 0xd0, 0xda, 0xd3,
+               0xd1, 0xd4, 0xd2, 0xd7, 0xd8, 0xd2, 0xd5, 0xdc,
+               0xdb, 0xd1, 0xdc, 0xda, 0xd4, 0xde, 0xdf, 0xd9,
+               0xda, 0xd3, 0xd6, 0xdf, 0xd9, 0xd0, 0xd0, 0xd6,
+               0xdc, 0xda, 0xdb, 0xd1, 0xd7, 0xdd, 0xdd, 0xd8,
+               0xdf, 0xd9, 0xd1, 0xd4, 0xd3, 0xd5, 0xde, 0xdb,
+               0xd5, 0xdc, 0xd2, 0xd7, 0xd8, 0xd2, 0xd4, 0xde,
+               0x87, 0x8d, 0x8d, 0x88, 0x8e, 0x8b, 0x83, 0x85,
+               0x80, 0x86, 0x86, 0x8f, 0x89, 0x80, 0x8a, 0x83,
+               0x81, 0x84, 0x82, 0x87, 0x88, 0x82, 0x85, 0x8c,
+               0x8b, 0x81, 0x8c, 0x8a, 0x84, 0x8e, 0x8f, 0x89,
+               0x8a, 0x83, 0x86, 0x8f, 0x89, 0x80, 0x80, 0x86,
+               0x8c, 0x8a, 0x8b, 0x81, 0x87, 0x8d, 0x8d, 0x88,
+               0x8f, 0x89, 0x81, 0x84, 0x83, 0x85, 0x8e, 0x8b,
+               0x85, 0x8c, 0x82, 0x87, 0x88, 0x82, 0x84, 0x8e,
+               0xc7, 0xcd, 0xcd, 0xc8, 0xce, 0xcb, 0xc3, 0xc5,
+               0xc0, 0xc6, 0xc6, 0xcf, 0xc9, 0xc0, 0xca, 0xc3,
+               0xc1, 0xc4, 0xc2, 0xc7, 0xc8, 0xc2, 0xc5, 0xcc,
+               0xcb, 0xc1, 0xcc, 0xca, 0xc4, 0xce, 0xcf, 0xc9,
+               0xca, 0xc3, 0xc6, 0xcf, 0xc9, 0xc0, 0xc0, 0xc6,
+               0xcc, 0xca, 0xcb, 0xc1, 0xc7, 0xcd, 0xcd, 0xc8,
+               0xcf, 0xc9, 0xc1, 0xc4, 0xc3, 0xc5, 0xce, 0xcb,
+               0xc5, 0xcc, 0xc2, 0xc7, 0xc8, 0xc2, 0xc4, 0xce,
+               0x57, 0x5d, 0x5d, 0x58, 0x5e, 0x5b, 0x53, 0x55,
+               0x50, 0x56, 0x56, 0x5f, 0x59, 0x50, 0x5a, 0x53,
+               0x51, 0x54, 0x52, 0x57, 0x58, 0x52, 0x55, 0x5c,
+               0x5b, 0x51, 0x5c, 0x5a, 0x54, 0x5e, 0x5f, 0x59,
+               0x5a, 0x53, 0x56, 0x5f, 0x59, 0x50, 0x50, 0x56,
+               0x5c, 0x5a, 0x5b, 0x51, 0x57, 0x5d, 0x5d, 0x58,
+               0x5f, 0x59, 0x51, 0x54, 0x53, 0x55, 0x5e, 0x5b,
+               0x55, 0x5c, 0x52, 0x57, 0x58, 0x52, 0x54, 0x5e,
+               0x77, 0x7d, 0x7d, 0x78, 0x7e, 0x7b, 0x73, 0x75,
+               0x70, 0x76, 0x76, 0x7f, 0x79, 0x70, 0x7a, 0x73,
+               0x71, 0x74, 0x72, 0x77, 0x78, 0x72, 0x75, 0x7c,
+               0x7b, 0x71, 0x7c, 0x7a, 0x74, 0x7e, 0x7f, 0x79,
+               0x7a, 0x73, 0x76, 0x7f, 0x79, 0x70, 0x70, 0x76,
+               0x7c, 0x7a, 0x7b, 0x71, 0x77, 0x7d, 0x7d, 0x78,
+               0x7f, 0x79, 0x71, 0x74, 0x73, 0x75, 0x7e, 0x7b,
+               0x75, 0x7c, 0x72, 0x77, 0x78, 0x72, 0x74, 0x7e,
+               0xe7, 0xed, 0xed, 0xe8, 0xee, 0xeb, 0xe3, 0xe5,
+               0xe0, 0xe6, 0xe6, 0xef, 0xe9, 0xe0, 0xea, 0xe3,
+               0xe1, 0xe4, 0xe2, 0xe7, 0xe8, 0xe2, 0xe5, 0xec,
+               0xeb, 0xe1, 0xec, 0xea, 0xe4, 0xee, 0xef, 0xe9,
+               0xea, 0xe3, 0xe6, 0xef, 0xe9, 0xe0, 0xe0, 0xe6,
+               0xec, 0xea, 0xeb, 0xe1, 0xe7, 0xed, 0xed, 0xe8,
+               0xef, 0xe9, 0xe1, 0xe4, 0xe3, 0xe5, 0xee, 0xeb,
+               0xe5, 0xec, 0xe2, 0xe7, 0xe8, 0xe2, 0xe4, 0xee,
+               0xb7, 0xbd, 0xbd, 0xb8, 0xbe, 0xbb, 0xb3, 0xb5,
+               0xb0, 0xb6, 0xb6, 0xbf, 0xb9, 0xb0, 0xba, 0xb3,
+               0xb1, 0xb4, 0xb2, 0xb7, 0xb8, 0xb2, 0xb5, 0xbc,
+               0xbb, 0xb1, 0xbc, 0xba, 0xb4, 0xbe, 0xbf, 0xb9,
+               0xba, 0xb3, 0xb6, 0xbf, 0xb9, 0xb0, 0xb0, 0xb6,
+               0xbc, 0xba, 0xbb, 0xb1, 0xb7, 0xbd, 0xbd, 0xb8,
+               0xbf, 0xb9, 0xb1, 0xb4, 0xb3, 0xb5, 0xbe, 0xbb,
+               0xb5, 0xbc, 0xb2, 0xb7, 0xb8, 0xb2, 0xb4, 0xbe,
+               0xc7, 0xcd, 0xcd, 0xc8, 0xce, 0xcb, 0xc3, 0xc5,
+               0xc0, 0xc6, 0xc6, 0xcf, 0xc9, 0xc0, 0xca, 0xc3,
+               0xc1, 0xc4, 0xc2, 0xc7, 0xc8, 0xc2, 0xc5, 0xcc,
+               0xcb, 0xc1, 0xcc, 0xca, 0xc4, 0xce, 0xcf, 0xc9,
+               0xca, 0xc3, 0xc6, 0xcf, 0xc9, 0xc0, 0xc0, 0xc6,
+               0xcc, 0xca, 0xcb, 0xc1, 0xc7, 0xcd, 0xcd, 0xc8,
+               0xcf, 0xc9, 0xc1, 0xc4, 0xc3, 0xc5, 0xce, 0xcb,
+               0xc5, 0xcc, 0xc2, 0xc7, 0xc8, 0xc2, 0xc4, 0xce,
+               0x47, 0x4d, 0x4d, 0x48, 0x4e, 0x4b, 0x43, 0x45,
+               0x40, 0x46, 0x46, 0x4f, 0x49, 0x40, 0x4a, 0x43,
+               0x41, 0x44, 0x42, 0x47, 0x48, 0x42, 0x45, 0x4c,
+               0x4b, 0x41, 0x4c, 0x4a, 0x44, 0x4e, 0x4f, 0x49,
+               0x4a, 0x43, 0x46, 0x4f, 0x49, 0x40, 0x40, 0x46,
+               0x4c, 0x4a, 0x4b, 0x41, 0x47, 0x4d, 0x4d, 0x48,
+               0x4f, 0x49, 0x41, 0x44, 0x43, 0x45, 0x4e, 0x4b,
+               0x45, 0x4c, 0x42, 0x47, 0x48, 0x42, 0x44, 0x4e,
+               0xb7, 0xbd, 0xbd, 0xb8, 0xbe, 0xbb, 0xb3, 0xb5,
+               0xb0, 0xb6, 0xb6, 0xbf, 0xb9, 0xb0, 0xba, 0xb3,
+               0xb1, 0xb4, 0xb2, 0xb7, 0xb8, 0xb2, 0xb5, 0xbc,
+               0xbb, 0xb1, 0xbc, 0xba, 0xb4, 0xbe, 0xbf, 0xb9,
+               0xba, 0xb3, 0xb6, 0xbf, 0xb9, 0xb0, 0xb0, 0xb6,
+               0xbc, 0xba, 0xbb, 0xb1, 0xb7, 0xbd, 0xbd, 0xb8,
+               0xbf, 0xb9, 0xb1, 0xb4, 0xb3, 0xb5, 0xbe, 0xbb,
+               0xb5, 0xbc, 0xb2, 0xb7, 0xb8, 0xb2, 0xb4, 0xbe,
+               0x27, 0x2d, 0x2d, 0x28, 0x2e, 0x2b, 0x23, 0x25,
+               0x20, 0x26, 0x26, 0x2f, 0x29, 0x20, 0x2a, 0x23,
+               0x21, 0x24, 0x22, 0x27, 0x28, 0x22, 0x25, 0x2c,
+               0x2b, 0x21, 0x2c, 0x2a, 0x24, 0x2e, 0x2f, 0x29,
+               0x2a, 0x23, 0x26, 0x2f, 0x29, 0x20, 0x20, 0x26,
+               0x2c, 0x2a, 0x2b, 0x21, 0x27, 0x2d, 0x2d, 0x28,
+               0x2f, 0x29, 0x21, 0x24, 0x23, 0x25, 0x2e, 0x2b,
+               0x25, 0x2c, 0x22, 0x27, 0x28, 0x22, 0x24, 0x2e,
+               0xf7, 0xfd, 0xfd, 0xf8, 0xfe, 0xfb, 0xf3, 0xf5,
+               0xf0, 0xf6, 0xf6, 0xff, 0xf9, 0xf0, 0xfa, 0xf3,
+               0xf1, 0xf4, 0xf2, 0xf7, 0xf8, 0xf2, 0xf5, 0xfc,
+               0xfb, 0xf1, 0xfc, 0xfa, 0xf4, 0xfe, 0xff, 0xf9,
+               0xfa, 0xf3, 0xf6, 0xff, 0xf9, 0xf0, 0xf0, 0xf6,
+               0xfc, 0xfa, 0xfb, 0xf1, 0xf7, 0xfd, 0xfd, 0xf8,
+               0xff, 0xf9, 0xf1, 0xf4, 0xf3, 0xf5, 0xfe, 0xfb,
+               0xf5, 0xfc, 0xf2, 0xf7, 0xf8, 0xf2, 0xf4, 0xfe,
+               0x87, 0x8d, 0x8d, 0x88, 0x8e, 0x8b, 0x83, 0x85,
+               0x80, 0x86, 0x86, 0x8f, 0x89, 0x80, 0x8a, 0x83,
+               0x81, 0x84, 0x82, 0x87, 0x88, 0x82, 0x85, 0x8c,
+               0x8b, 0x81, 0x8c, 0x8a, 0x84, 0x8e, 0x8f, 0x89,
+               0x8a, 0x83, 0x86, 0x8f, 0x89, 0x80, 0x80, 0x86,
+               0x8c, 0x8a, 0x8b, 0x81, 0x87, 0x8d, 0x8d, 0x88,
+               0x8f, 0x89, 0x81, 0x84, 0x83, 0x85, 0x8e, 0x8b,
+               0x85, 0x8c, 0x82, 0x87, 0x88, 0x82, 0x84, 0x8e,
+               0x17, 0x1d, 0x1d, 0x18, 0x1e, 0x1b, 0x13, 0x15,
+               0x10, 0x16, 0x16, 0x1f, 0x19, 0x10, 0x1a, 0x13,
+               0x11, 0x14, 0x12, 0x17, 0x18, 0x12, 0x15, 0x1c,
+               0x1b, 0x11, 0x1c, 0x1a, 0x14, 0x1e, 0x1f, 0x19,
+               0x1a, 0x13, 0x16, 0x1f, 0x19, 0x10, 0x10, 0x16,
+               0x1c, 0x1a, 0x1b, 0x11, 0x17, 0x1d, 0x1d, 0x18,
+               0x1f, 0x19, 0x11, 0x14, 0x13, 0x15, 0x1e, 0x1b,
+               0x15, 0x1c, 0x12, 0x17, 0x18, 0x12, 0x14, 0x1e,
+               0xd7, 0xdd, 0xdd, 0xd8, 0xde, 0xdb, 0xd3, 0xd5,
+               0xd0, 0xd6, 0xd6, 0xdf, 0xd9, 0xd0, 0xda, 0xd3,
+               0xd1, 0xd4, 0xd2, 0xd7, 0xd8, 0xd2, 0xd5, 0xdc,
+               0xdb, 0xd1, 0xdc, 0xda, 0xd4, 0xde, 0xdf, 0xd9,
+               0xda, 0xd3, 0xd6, 0xdf, 0xd9, 0xd0, 0xd0, 0xd6,
+               0xdc, 0xda, 0xdb, 0xd1, 0xd7, 0xdd, 0xdd, 0xd8,
+               0xdf, 0xd9, 0xd1, 0xd4, 0xd3, 0xd5, 0xde, 0xdb,
+               0xd5, 0xdc, 0xd2, 0xd7, 0xd8, 0xd2, 0xd4, 0xde,
+               0x17, 0x1d, 0x1d, 0x18, 0x1e, 0x1b, 0x13, 0x15,
+               0x10, 0x16, 0x16, 0x1f, 0x19, 0x10, 0x1a, 0x13,
+               0x11, 0x14, 0x12, 0x17, 0x18, 0x12, 0x15, 0x1c,
+               0x1b, 0x11, 0x1c, 0x1a, 0x14, 0x1e, 0x1f, 0x19,
+               0x1a, 0x13, 0x16, 0x1f, 0x19, 0x10, 0x10, 0x16,
+               0x1c, 0x1a, 0x1b, 0x11, 0x17, 0x1d, 0x1d, 0x18,
+               0x1f, 0x19, 0x11, 0x14, 0x13, 0x15, 0x1e, 0x1b,
+               0x15, 0x1c, 0x12, 0x17, 0x18, 0x12, 0x14, 0x1e,
+               0x67, 0x6d, 0x6d, 0x68, 0x6e, 0x6b, 0x63, 0x65,
+               0x60, 0x66, 0x66, 0x6f, 0x69, 0x60, 0x6a, 0x63,
+               0x61, 0x64, 0x62, 0x67, 0x68, 0x62, 0x65, 0x6c,
+               0x6b, 0x61, 0x6c, 0x6a, 0x64, 0x6e, 0x6f, 0x69,
+               0x6a, 0x63, 0x66, 0x6f, 0x69, 0x60, 0x60, 0x66,
+               0x6c, 0x6a, 0x6b, 0x61, 0x67, 0x6d, 0x6d, 0x68,
+               0x6f, 0x69, 0x61, 0x64, 0x63, 0x65, 0x6e, 0x6b,
+               0x65, 0x6c, 0x62, 0x67, 0x68, 0x62, 0x64, 0x6e,
+               0xa7, 0xad, 0xad, 0xa8, 0xae, 0xab, 0xa3, 0xa5,
+               0xa0, 0xa6, 0xa6, 0xaf, 0xa9, 0xa0, 0xaa, 0xa3,
+               0xa1, 0xa4, 0xa2, 0xa7, 0xa8, 0xa2, 0xa5, 0xac,
+               0xab, 0xa1, 0xac, 0xaa, 0xa4, 0xae, 0xaf, 0xa9,
+               0xaa, 0xa3, 0xa6, 0xaf, 0xa9, 0xa0, 0xa0, 0xa6,
+               0xac, 0xaa, 0xab, 0xa1, 0xa7, 0xad, 0xad, 0xa8,
+               0xaf, 0xa9, 0xa1, 0xa4, 0xa3, 0xa5, 0xae, 0xab,
+               0xa5, 0xac, 0xa2, 0xa7, 0xa8, 0xa2, 0xa4, 0xae,
+               0x47, 0x4d, 0x4d, 0x48, 0x4e, 0x4b, 0x43, 0x45,
+               0x40, 0x46, 0x46, 0x4f, 0x49, 0x40, 0x4a, 0x43,
+               0x41, 0x44, 0x42, 0x47, 0x48, 0x42, 0x45, 0x4c,
+               0x4b, 0x41, 0x4c, 0x4a, 0x44, 0x4e, 0x4f, 0x49,
+               0x4a, 0x43, 0x46, 0x4f, 0x49, 0x40, 0x40, 0x46,
+               0x4c, 0x4a, 0x4b, 0x41, 0x47, 0x4d, 0x4d, 0x48,
+               0x4f, 0x49, 0x41, 0x44, 0x43, 0x45, 0x4e, 0x4b,
+               0x45, 0x4c, 0x42, 0x47, 0x48, 0x42, 0x44, 0x4e,
+               0xd7, 0xdd, 0xdd, 0xd8, 0xde, 0xdb, 0xd3, 0xd5,
+               0xd0, 0xd6, 0xd6, 0xdf, 0xd9, 0xd0, 0xda, 0xd3,
+               0xd1, 0xd4, 0xd2, 0xd7, 0xd8, 0xd2, 0xd5, 0xdc,
+               0xdb, 0xd1, 0xdc, 0xda, 0xd4, 0xde, 0xdf, 0xd9,
+               0xda, 0xd3, 0xd6, 0xdf, 0xd9, 0xd0, 0xd0, 0xd6,
+               0xdc, 0xda, 0xdb, 0xd1, 0xd7, 0xdd, 0xdd, 0xd8,
+               0xdf, 0xd9, 0xd1, 0xd4, 0xd3, 0xd5, 0xde, 0xdb,
+               0xd5, 0xdc, 0xd2, 0xd7, 0xd8, 0xd2, 0xd4, 0xde,
+               0x97, 0x9d, 0x9d, 0x98, 0x9e, 0x9b, 0x93, 0x95,
+               0x90, 0x96, 0x96, 0x9f, 0x99, 0x90, 0x9a, 0x93,
+               0x91, 0x94, 0x92, 0x97, 0x98, 0x92, 0x95, 0x9c,
+               0x9b, 0x91, 0x9c, 0x9a, 0x94, 0x9e, 0x9f, 0x99,
+               0x9a, 0x93, 0x96, 0x9f, 0x99, 0x90, 0x90, 0x96,
+               0x9c, 0x9a, 0x9b, 0x91, 0x97, 0x9d, 0x9d, 0x98,
+               0x9f, 0x99, 0x91, 0x94, 0x93, 0x95, 0x9e, 0x9b,
+               0x95, 0x9c, 0x92, 0x97, 0x98, 0x92, 0x94, 0x9e,
+               0x07, 0x0d, 0x0d, 0x08, 0x0e, 0x0b, 0x03, 0x05,
+               0x00, 0x06, 0x06, 0x0f, 0x09, 0x00, 0x0a, 0x03,
+               0x01, 0x04, 0x02, 0x07, 0x08, 0x02, 0x05, 0x0c,
+               0x0b, 0x01, 0x0c, 0x0a, 0x04, 0x0e, 0x0f, 0x09,
+               0x0a, 0x03, 0x06, 0x0f, 0x09, 0x00, 0x00, 0x06,
+               0x0c, 0x0a, 0x0b, 0x01, 0x07, 0x0d, 0x0d, 0x08,
+               0x0f, 0x09, 0x01, 0x04, 0x03, 0x05, 0x0e, 0x0b,
+               0x05, 0x0c, 0x02, 0x07, 0x08, 0x02, 0x04, 0x0e,
+               0x87, 0x8d, 0x8d, 0x88, 0x8e, 0x8b, 0x83, 0x85,
+               0x80, 0x86, 0x86, 0x8f, 0x89, 0x80, 0x8a, 0x83,
+               0x81, 0x84, 0x82, 0x87, 0x88, 0x82, 0x85, 0x8c,
+               0x8b, 0x81, 0x8c, 0x8a, 0x84, 0x8e, 0x8f, 0x89,
+               0x8a, 0x83, 0x86, 0x8f, 0x89, 0x80, 0x80, 0x86,
+               0x8c, 0x8a, 0x8b, 0x81, 0x87, 0x8d, 0x8d, 0x88,
+               0x8f, 0x89, 0x81, 0x84, 0x83, 0x85, 0x8e, 0x8b,
+               0x85, 0x8c, 0x82, 0x87, 0x88, 0x82, 0x84, 0x8e,
+               0x67, 0x6d, 0x6d, 0x68, 0x6e, 0x6b, 0x63, 0x65,
+               0x60, 0x66, 0x66, 0x6f, 0x69, 0x60, 0x6a, 0x63,
+               0x61, 0x64, 0x62, 0x67, 0x68, 0x62, 0x65, 0x6c,
+               0x6b, 0x61, 0x6c, 0x6a, 0x64, 0x6e, 0x6f, 0x69,
+               0x6a, 0x63, 0x66, 0x6f, 0x69, 0x60, 0x60, 0x66,
+               0x6c, 0x6a, 0x6b, 0x61, 0x67, 0x6d, 0x6d, 0x68,
+               0x6f, 0x69, 0x61, 0x64, 0x63, 0x65, 0x6e, 0x6b,
+               0x65, 0x6c, 0x62, 0x67, 0x68, 0x62, 0x64, 0x6e,
+               0xf7, 0xfd, 0xfd, 0xf8, 0xfe, 0xfb, 0xf3, 0xf5,
+               0xf0, 0xf6, 0xf6, 0xff, 0xf9, 0xf0, 0xfa, 0xf3,
+               0xf1, 0xf4, 0xf2, 0xf7, 0xf8, 0xf2, 0xf5, 0xfc,
+               0xfb, 0xf1, 0xfc, 0xfa, 0xf4, 0xfe, 0xff, 0xf9,
+               0xfa, 0xf3, 0xf6, 0xff, 0xf9, 0xf0, 0xf0, 0xf6,
+               0xfc, 0xfa, 0xfb, 0xf1, 0xf7, 0xfd, 0xfd, 0xf8,
+               0xff, 0xf9, 0xf1, 0xf4, 0xf3, 0xf5, 0xfe, 0xfb,
+               0xf5, 0xfc, 0xf2, 0xf7, 0xf8, 0xf2, 0xf4, 0xfe,
+               0x97, 0x9d, 0x9d, 0x98, 0x9e, 0x9b, 0x93, 0x95,
+               0x90, 0x96, 0x96, 0x9f, 0x99, 0x90, 0x9a, 0x93,
+               0x91, 0x94, 0x92, 0x97, 0x98, 0x92, 0x95, 0x9c,
+               0x9b, 0x91, 0x9c, 0x9a, 0x94, 0x9e, 0x9f, 0x99,
+               0x9a, 0x93, 0x96, 0x9f, 0x99, 0x90, 0x90, 0x96,
+               0x9c, 0x9a, 0x9b, 0x91, 0x97, 0x9d, 0x9d, 0x98,
+               0x9f, 0x99, 0x91, 0x94, 0x93, 0x95, 0x9e, 0x9b,
+               0x95, 0x9c, 0x92, 0x97, 0x98, 0x92, 0x94, 0x9e,
+               0x37, 0x3d, 0x3d, 0x38, 0x3e, 0x3b, 0x33, 0x35,
+               0x30, 0x36, 0x36, 0x3f, 0x39, 0x30, 0x3a, 0x33,
+               0x31, 0x34, 0x32, 0x37, 0x38, 0x32, 0x35, 0x3c,
+               0x3b, 0x31, 0x3c, 0x3a, 0x34, 0x3e, 0x3f, 0x39,
+               0x3a, 0x33, 0x36, 0x3f, 0x39, 0x30, 0x30, 0x36,
+               0x3c, 0x3a, 0x3b, 0x31, 0x37, 0x3d, 0x3d, 0x38,
+               0x3f, 0x39, 0x31, 0x34, 0x33, 0x35, 0x3e, 0x3b,
+               0x35, 0x3c, 0x32, 0x37, 0x38, 0x32, 0x34, 0x3e,
+               0x87, 0x8d, 0x8d, 0x88, 0x8e, 0x8b, 0x83, 0x85,
+               0x80, 0x86, 0x86, 0x8f, 0x89, 0x80, 0x8a, 0x83,
+               0x81, 0x84, 0x82, 0x87, 0x88, 0x82, 0x85, 0x8c,
+               0x8b, 0x81, 0x8c, 0x8a, 0x84, 0x8e, 0x8f, 0x89,
+               0x8a, 0x83, 0x86, 0x8f, 0x89, 0x80, 0x80, 0x86,
+               0x8c, 0x8a, 0x8b, 0x81, 0x87, 0x8d, 0x8d, 0x88,
+               0x8f, 0x89, 0x81, 0x84, 0x83, 0x85, 0x8e, 0x8b,
+               0x85, 0x8c, 0x82, 0x87, 0x88, 0x82, 0x84, 0x8e,
+               0x07, 0x0d, 0x0d, 0x08, 0x0e, 0x0b, 0x03, 0x05,
+               0x00, 0x06, 0x06, 0x0f, 0x09, 0x00, 0x0a, 0x03,
+               0x01, 0x04, 0x02, 0x07, 0x08, 0x02, 0x05, 0x0c,
+               0x0b, 0x01, 0x0c, 0x0a, 0x04, 0x0e, 0x0f, 0x09,
+               0x0a, 0x03, 0x06, 0x0f, 0x09, 0x00, 0x00, 0x06,
+               0x0c, 0x0a, 0x0b, 0x01, 0x07, 0x0d, 0x0d, 0x08,
+               0x0f, 0x09, 0x01, 0x04, 0x03, 0x05, 0x0e, 0x0b,
+               0x05, 0x0c, 0x02, 0x07, 0x08, 0x02, 0x04, 0x0e,
+               0x77, 0x7d, 0x7d, 0x78, 0x7e, 0x7b, 0x73, 0x75,
+               0x70, 0x76, 0x76, 0x7f, 0x79, 0x70, 0x7a, 0x73,
+               0x71, 0x74, 0x72, 0x77, 0x78, 0x72, 0x75, 0x7c,
+               0x7b, 0x71, 0x7c, 0x7a, 0x74, 0x7e, 0x7f, 0x79,
+               0x7a, 0x73, 0x76, 0x7f, 0x79, 0x70, 0x70, 0x76,
+               0x7c, 0x7a, 0x7b, 0x71, 0x77, 0x7d, 0x7d, 0x78,
+               0x7f, 0x79, 0x71, 0x74, 0x73, 0x75, 0x7e, 0x7b,
+               0x75, 0x7c, 0x72, 0x77, 0x78, 0x72, 0x74, 0x7e,
+               0xb7, 0xbd, 0xbd, 0xb8, 0xbe, 0xbb, 0xb3, 0xb5,
+               0xb0, 0xb6, 0xb6, 0xbf, 0xb9, 0xb0, 0xba, 0xb3,
+               0xb1, 0xb4, 0xb2, 0xb7, 0xb8, 0xb2, 0xb5, 0xbc,
+               0xbb, 0xb1, 0xbc, 0xba, 0xb4, 0xbe, 0xbf, 0xb9,
+               0xba, 0xb3, 0xb6, 0xbf, 0xb9, 0xb0, 0xb0, 0xb6,
+               0xbc, 0xba, 0xbb, 0xb1, 0xb7, 0xbd, 0xbd, 0xb8,
+               0xbf, 0xb9, 0xb1, 0xb4, 0xb3, 0xb5, 0xbe, 0xbb,
+               0xb5, 0xbc, 0xb2, 0xb7, 0xb8, 0xb2, 0xb4, 0xbe,
+               0x47, 0x4d, 0x4d, 0x48, 0x4e, 0x4b, 0x43, 0x45,
+               0x40, 0x46, 0x46, 0x4f, 0x49, 0x40, 0x4a, 0x43,
+               0x41, 0x44, 0x42, 0x47, 0x48, 0x42, 0x45, 0x4c,
+               0x4b, 0x41, 0x4c, 0x4a, 0x44, 0x4e, 0x4f, 0x49,
+               0x4a, 0x43, 0x46, 0x4f, 0x49, 0x40, 0x40, 0x46,
+               0x4c, 0x4a, 0x4b, 0x41, 0x47, 0x4d, 0x4d, 0x48,
+               0x4f, 0x49, 0x41, 0x44, 0x43, 0x45, 0x4e, 0x4b,
+               0x45, 0x4c, 0x42, 0x47, 0x48, 0x42, 0x44, 0x4e,
+               0x17, 0x1d, 0x1d, 0x18, 0x1e, 0x1b, 0x13, 0x15,
+               0x10, 0x16, 0x16, 0x1f, 0x19, 0x10, 0x1a, 0x13,
+               0x11, 0x14, 0x12, 0x17, 0x18, 0x12, 0x15, 0x1c,
+               0x1b, 0x11, 0x1c, 0x1a, 0x14, 0x1e, 0x1f, 0x19,
+               0x1a, 0x13, 0x16, 0x1f, 0x19, 0x10, 0x10, 0x16,
+               0x1c, 0x1a, 0x1b, 0x11, 0x17, 0x1d, 0x1d, 0x18,
+               0x1f, 0x19, 0x11, 0x14, 0x13, 0x15, 0x1e, 0x1b,
+               0x15, 0x1c, 0x12, 0x17, 0x18, 0x12, 0x14, 0x1e,
+               0xf7, 0xfd, 0xfd, 0xf8, 0xfe, 0xfb, 0xf3, 0xf5,
+               0xf0, 0xf6, 0xf6, 0xff, 0xf9, 0xf0, 0xfa, 0xf3,
+               0xf1, 0xf4, 0xf2, 0xf7, 0xf8, 0xf2, 0xf5, 0xfc,
+               0xfb, 0xf1, 0xfc, 0xfa, 0xf4, 0xfe, 0xff, 0xf9,
+               0xfa, 0xf3, 0xf6, 0xff, 0xf9, 0xf0, 0xf0, 0xf6,
+               0xfc, 0xfa, 0xfb, 0xf1, 0xf7, 0xfd, 0xfd, 0xf8,
+               0xff, 0xf9, 0xf1, 0xf4, 0xf3, 0xf5, 0xfe, 0xfb,
+               0xf5, 0xfc, 0xf2, 0xf7, 0xf8, 0xf2, 0xf4, 0xfe,
+               0x27, 0x2d, 0x2d, 0x28, 0x2e, 0x2b, 0x23, 0x25,
+               0x20, 0x26, 0x26, 0x2f, 0x29, 0x20, 0x2a, 0x23,
+               0x21, 0x24, 0x22, 0x27, 0x28, 0x22, 0x25, 0x2c,
+               0x2b, 0x21, 0x2c, 0x2a, 0x24, 0x2e, 0x2f, 0x29,
+               0x2a, 0x23, 0x26, 0x2f, 0x29, 0x20, 0x20, 0x26,
+               0x2c, 0x2a, 0x2b, 0x21, 0x27, 0x2d, 0x2d, 0x28,
+               0x2f, 0x29, 0x21, 0x24, 0x23, 0x25, 0x2e, 0x2b,
+               0x25, 0x2c, 0x22, 0x27, 0x28, 0x22, 0x24, 0x2e,
+               0xe7, 0xed, 0xed, 0xe8, 0xee, 0xeb, 0xe3, 0xe5,
+               0xe0, 0xe6, 0xe6, 0xef, 0xe9, 0xe0, 0xea, 0xe3,
+               0xe1, 0xe4, 0xe2, 0xe7, 0xe8, 0xe2, 0xe5, 0xec,
+               0xeb, 0xe1, 0xec, 0xea, 0xe4, 0xee, 0xef, 0xe9,
+               0xea, 0xe3, 0xe6, 0xef, 0xe9, 0xe0, 0xe0, 0xe6,
+               0xec, 0xea, 0xeb, 0xe1, 0xe7, 0xed, 0xed, 0xe8,
+               0xef, 0xe9, 0xe1, 0xe4, 0xe3, 0xe5, 0xee, 0xeb,
+               0xe5, 0xec, 0xe2, 0xe7, 0xe8, 0xe2, 0xe4, 0xee,
+               0xc7, 0xcd, 0xcd, 0xc8, 0xce, 0xcb, 0xc3, 0xc5,
+               0xc0, 0xc6, 0xc6, 0xcf, 0xc9, 0xc0, 0xca, 0xc3,
+               0xc1, 0xc4, 0xc2, 0xc7, 0xc8, 0xc2, 0xc5, 0xcc,
+               0xcb, 0xc1, 0xcc, 0xca, 0xc4, 0xce, 0xcf, 0xc9,
+               0xca, 0xc3, 0xc6, 0xcf, 0xc9, 0xc0, 0xc0, 0xc6,
+               0xcc, 0xca, 0xcb, 0xc1, 0xc7, 0xcd, 0xcd, 0xc8,
+               0xcf, 0xc9, 0xc1, 0xc4, 0xc3, 0xc5, 0xce, 0xcb,
+               0xc5, 0xcc, 0xc2, 0xc7, 0xc8, 0xc2, 0xc4, 0xce,
+               0x37, 0x3d, 0x3d, 0x38, 0x3e, 0x3b, 0x33, 0x35,
+               0x30, 0x36, 0x36, 0x3f, 0x39, 0x30, 0x3a, 0x33,
+               0x31, 0x34, 0x32, 0x37, 0x38, 0x32, 0x35, 0x3c,
+               0x3b, 0x31, 0x3c, 0x3a, 0x34, 0x3e, 0x3f, 0x39,
+               0x3a, 0x33, 0x36, 0x3f, 0x39, 0x30, 0x30, 0x36,
+               0x3c, 0x3a, 0x3b, 0x31, 0x37, 0x3d, 0x3d, 0x38,
+               0x3f, 0x39, 0x31, 0x34, 0x33, 0x35, 0x3e, 0x3b,
+               0x35, 0x3c, 0x32, 0x37, 0x38, 0x32, 0x34, 0x3e,
+               0x57, 0x5d, 0x5d, 0x58, 0x5e, 0x5b, 0x53, 0x55,
+               0x50, 0x56, 0x56, 0x5f, 0x59, 0x50, 0x5a, 0x53,
+               0x51, 0x54, 0x52, 0x57, 0x58, 0x52, 0x55, 0x5c,
+               0x5b, 0x51, 0x5c, 0x5a, 0x54, 0x5e, 0x5f, 0x59,
+               0x5a, 0x53, 0x56, 0x5f, 0x59, 0x50, 0x50, 0x56,
+               0x5c, 0x5a, 0x5b, 0x51, 0x57, 0x5d, 0x5d, 0x58,
+               0x5f, 0x59, 0x51, 0x54, 0x53, 0x55, 0x5e, 0x5b,
+               0x55, 0x5c, 0x52, 0x57, 0x58, 0x52, 0x54, 0x5e,
+               0xb7, 0xbd, 0xbd, 0xb8, 0xbe, 0xbb, 0xb3, 0xb5,
+               0xb0, 0xb6, 0xb6, 0xbf, 0xb9, 0xb0, 0xba, 0xb3,
+               0xb1, 0xb4, 0xb2, 0xb7, 0xb8, 0xb2, 0xb5, 0xbc,
+               0xbb, 0xb1, 0xbc, 0xba, 0xb4, 0xbe, 0xbf, 0xb9,
+               0xba, 0xb3, 0xb6, 0xbf, 0xb9, 0xb0, 0xb0, 0xb6,
+               0xbc, 0xba, 0xbb, 0xb1, 0xb7, 0xbd, 0xbd, 0xb8,
+               0xbf, 0xb9, 0xb1, 0xb4, 0xb3, 0xb5, 0xbe, 0xbb,
+               0xb5, 0xbc, 0xb2, 0xb7, 0xb8, 0xb2, 0xb4, 0xbe,
+               0xa7, 0xad, 0xad, 0xa8, 0xae, 0xab, 0xa3, 0xa5,
+               0xa0, 0xa6, 0xa6, 0xaf, 0xa9, 0xa0, 0xaa, 0xa3,
+               0xa1, 0xa4, 0xa2, 0xa7, 0xa8, 0xa2, 0xa5, 0xac,
+               0xab, 0xa1, 0xac, 0xaa, 0xa4, 0xae, 0xaf, 0xa9,
+               0xaa, 0xa3, 0xa6, 0xaf, 0xa9, 0xa0, 0xa0, 0xa6,
+               0xac, 0xaa, 0xab, 0xa1, 0xa7, 0xad, 0xad, 0xa8,
+               0xaf, 0xa9, 0xa1, 0xa4, 0xa3, 0xa5, 0xae, 0xab,
+               0xa5, 0xac, 0xa2, 0xa7, 0xa8, 0xa2, 0xa4, 0xae,
+               0x57, 0x5d, 0x5d, 0x58, 0x5e, 0x5b, 0x53, 0x55,
+               0x50, 0x56, 0x56, 0x5f, 0x59, 0x50, 0x5a, 0x53,
+               0x51, 0x54, 0x52, 0x57, 0x58, 0x52, 0x55, 0x5c,
+               0x5b, 0x51, 0x5c, 0x5a, 0x54, 0x5e, 0x5f, 0x59,
+               0x5a, 0x53, 0x56, 0x5f, 0x59, 0x50, 0x50, 0x56,
+               0x5c, 0x5a, 0x5b, 0x51, 0x57, 0x5d, 0x5d, 0x58,
+               0x5f, 0x59, 0x51, 0x54, 0x53, 0x55, 0x5e, 0x5b,
+               0x55, 0x5c, 0x52, 0x57, 0x58, 0x52, 0x54, 0x5e,
+               0xe7, 0xed, 0xed, 0xe8, 0xee, 0xeb, 0xe3, 0xe5,
+               0xe0, 0xe6, 0xe6, 0xef, 0xe9, 0xe0, 0xea, 0xe3,
+               0xe1, 0xe4, 0xe2, 0xe7, 0xe8, 0xe2, 0xe5, 0xec,
+               0xeb, 0xe1, 0xec, 0xea, 0xe4, 0xee, 0xef, 0xe9,
+               0xea, 0xe3, 0xe6, 0xef, 0xe9, 0xe0, 0xe0, 0xe6,
+               0xec, 0xea, 0xeb, 0xe1, 0xe7, 0xed, 0xed, 0xe8,
+               0xef, 0xe9, 0xe1, 0xe4, 0xe3, 0xe5, 0xee, 0xeb,
+               0xe5, 0xec, 0xe2, 0xe7, 0xe8, 0xe2, 0xe4, 0xee,
+               0x27, 0x2d, 0x2d, 0x28, 0x2e, 0x2b, 0x23, 0x25,
+               0x20, 0x26, 0x26, 0x2f, 0x29, 0x20, 0x2a, 0x23,
+               0x21, 0x24, 0x22, 0x27, 0x28, 0x22, 0x25, 0x2c,
+               0x2b, 0x21, 0x2c, 0x2a, 0x24, 0x2e, 0x2f, 0x29,
+               0x2a, 0x23, 0x26, 0x2f, 0x29, 0x20, 0x20, 0x26,
+               0x2c, 0x2a, 0x2b, 0x21, 0x27, 0x2d, 0x2d, 0x28,
+               0x2f, 0x29, 0x21, 0x24, 0x23, 0x25, 0x2e, 0x2b,
+               0x25, 0x2c, 0x22, 0x27, 0x28, 0x22, 0x24, 0x2e,
+               0x77, 0x7d, 0x7d, 0x78, 0x7e, 0x7b, 0x73, 0x75,
+               0x70, 0x76, 0x76, 0x7f, 0x79, 0x70, 0x7a, 0x73,
+               0x71, 0x74, 0x72, 0x77, 0x78, 0x72, 0x75, 0x7c,
+               0x7b, 0x71, 0x7c, 0x7a, 0x74, 0x7e, 0x7f, 0x79,
+               0x7a, 0x73, 0x76, 0x7f, 0x79, 0x70, 0x70, 0x76,
+               0x7c, 0x7a, 0x7b, 0x71, 0x77, 0x7d, 0x7d, 0x78,
+               0x7f, 0x79, 0x71, 0x74, 0x73, 0x75, 0x7e, 0x7b,
+               0x75, 0x7c, 0x72, 0x77, 0x78, 0x72, 0x74, 0x7e,
+               0xc7, 0xcd, 0xcd, 0xc8, 0xce, 0xcb, 0xc3, 0xc5,
+               0xc0, 0xc6, 0xc6, 0xcf, 0xc9, 0xc0, 0xca, 0xc3,
+               0xc1, 0xc4, 0xc2, 0xc7, 0xc8, 0xc2, 0xc5, 0xcc,
+               0xcb, 0xc1, 0xcc, 0xca, 0xc4, 0xce, 0xcf, 0xc9,
+               0xca, 0xc3, 0xc6, 0xcf, 0xc9, 0xc0, 0xc0, 0xc6,
+               0xcc, 0xca, 0xcb, 0xc1, 0xc7, 0xcd, 0xcd, 0xc8,
+               0xcf, 0xc9, 0xc1, 0xc4, 0xc3, 0xc5, 0xce, 0xcb,
+               0xc5, 0xcc, 0xc2, 0xc7, 0xc8, 0xc2, 0xc4, 0xce,
+       },{
+               0x2c, 0x2a, 0x21, 0x2f, 0x2a, 0x24, 0x2f, 0x22,
+               0x29, 0x27, 0x22, 0x2c, 0x26, 0x29, 0x28, 0x25,
+               0x20, 0x26, 0x2d, 0x21, 0x23, 0x2d, 0x24, 0x2e,
+               0x2e, 0x20, 0x27, 0x2b, 0x25, 0x23, 0x2b, 0x28,
+               0x29, 0x24, 0x2e, 0x23, 0x2f, 0x22, 0x25, 0x2c,
+               0x22, 0x29, 0x28, 0x25, 0x2c, 0x2f, 0x23, 0x2a,
+               0x27, 0x2b, 0x20, 0x2e, 0x24, 0x21, 0x2a, 0x27,
+               0x21, 0x26, 0x2d, 0x20, 0x2b, 0x28, 0x26, 0x2d,
+               0xec, 0xea, 0xe1, 0xef, 0xea, 0xe4, 0xef, 0xe2,
+               0xe9, 0xe7, 0xe2, 0xec, 0xe6, 0xe9, 0xe8, 0xe5,
+               0xe0, 0xe6, 0xed, 0xe1, 0xe3, 0xed, 0xe4, 0xee,
+               0xee, 0xe0, 0xe7, 0xeb, 0xe5, 0xe3, 0xeb, 0xe8,
+               0xe9, 0xe4, 0xee, 0xe3, 0xef, 0xe2, 0xe5, 0xec,
+               0xe2, 0xe9, 0xe8, 0xe5, 0xec, 0xef, 0xe3, 0xea,
+               0xe7, 0xeb, 0xe0, 0xee, 0xe4, 0xe1, 0xea, 0xe7,
+               0xe1, 0xe6, 0xed, 0xe0, 0xeb, 0xe8, 0xe6, 0xed,
+               0xcc, 0xca, 0xc1, 0xcf, 0xca, 0xc4, 0xcf, 0xc2,
+               0xc9, 0xc7, 0xc2, 0xcc, 0xc6, 0xc9, 0xc8, 0xc5,
+               0xc0, 0xc6, 0xcd, 0xc1, 0xc3, 0xcd, 0xc4, 0xce,
+               0xce, 0xc0, 0xc7, 0xcb, 0xc5, 0xc3, 0xcb, 0xc8,
+               0xc9, 0xc4, 0xce, 0xc3, 0xcf, 0xc2, 0xc5, 0xcc,
+               0xc2, 0xc9, 0xc8, 0xc5, 0xcc, 0xcf, 0xc3, 0xca,
+               0xc7, 0xcb, 0xc0, 0xce, 0xc4, 0xc1, 0xca, 0xc7,
+               0xc1, 0xc6, 0xcd, 0xc0, 0xcb, 0xc8, 0xc6, 0xcd,
+               0xbc, 0xba, 0xb1, 0xbf, 0xba, 0xb4, 0xbf, 0xb2,
+               0xb9, 0xb7, 0xb2, 0xbc, 0xb6, 0xb9, 0xb8, 0xb5,
+               0xb0, 0xb6, 0xbd, 0xb1, 0xb3, 0xbd, 0xb4, 0xbe,
+               0xbe, 0xb0, 0xb7, 0xbb, 0xb5, 0xb3, 0xbb, 0xb8,
+               0xb9, 0xb4, 0xbe, 0xb3, 0xbf, 0xb2, 0xb5, 0xbc,
+               0xb2, 0xb9, 0xb8, 0xb5, 0xbc, 0xbf, 0xb3, 0xba,
+               0xb7, 0xbb, 0xb0, 0xbe, 0xb4, 0xb1, 0xba, 0xb7,
+               0xb1, 0xb6, 0xbd, 0xb0, 0xbb, 0xb8, 0xb6, 0xbd,
+               0x4c, 0x4a, 0x41, 0x4f, 0x4a, 0x44, 0x4f, 0x42,
+               0x49, 0x47, 0x42, 0x4c, 0x46, 0x49, 0x48, 0x45,
+               0x40, 0x46, 0x4d, 0x41, 0x43, 0x4d, 0x44, 0x4e,
+               0x4e, 0x40, 0x47, 0x4b, 0x45, 0x43, 0x4b, 0x48,
+               0x49, 0x44, 0x4e, 0x43, 0x4f, 0x42, 0x45, 0x4c,
+               0x42, 0x49, 0x48, 0x45, 0x4c, 0x4f, 0x43, 0x4a,
+               0x47, 0x4b, 0x40, 0x4e, 0x44, 0x41, 0x4a, 0x47,
+               0x41, 0x46, 0x4d, 0x40, 0x4b, 0x48, 0x46, 0x4d,
+               0x2c, 0x2a, 0x21, 0x2f, 0x2a, 0x24, 0x2f, 0x22,
+               0x29, 0x27, 0x22, 0x2c, 0x26, 0x29, 0x28, 0x25,
+               0x20, 0x26, 0x2d, 0x21, 0x23, 0x2d, 0x24, 0x2e,
+               0x2e, 0x20, 0x27, 0x2b, 0x25, 0x23, 0x2b, 0x28,
+               0x29, 0x24, 0x2e, 0x23, 0x2f, 0x22, 0x25, 0x2c,
+               0x22, 0x29, 0x28, 0x25, 0x2c, 0x2f, 0x23, 0x2a,
+               0x27, 0x2b, 0x20, 0x2e, 0x24, 0x21, 0x2a, 0x27,
+               0x21, 0x26, 0x2d, 0x20, 0x2b, 0x28, 0x26, 0x2d,
+               0x1c, 0x1a, 0x11, 0x1f, 0x1a, 0x14, 0x1f, 0x12,
+               0x19, 0x17, 0x12, 0x1c, 0x16, 0x19, 0x18, 0x15,
+               0x10, 0x16, 0x1d, 0x11, 0x13, 0x1d, 0x14, 0x1e,
+               0x1e, 0x10, 0x17, 0x1b, 0x15, 0x13, 0x1b, 0x18,
+               0x19, 0x14, 0x1e, 0x13, 0x1f, 0x12, 0x15, 0x1c,
+               0x12, 0x19, 0x18, 0x15, 0x1c, 0x1f, 0x13, 0x1a,
+               0x17, 0x1b, 0x10, 0x1e, 0x14, 0x11, 0x1a, 0x17,
+               0x11, 0x16, 0x1d, 0x10, 0x1b, 0x18, 0x16, 0x1d,
+               0xcc, 0xca, 0xc1, 0xcf, 0xca, 0xc4, 0xcf, 0xc2,
+               0xc9, 0xc7, 0xc2, 0xcc, 0xc6, 0xc9, 0xc8, 0xc5,
+               0xc0, 0xc6, 0xcd, 0xc1, 0xc3, 0xcd, 0xc4, 0xce,
+               0xce, 0xc0, 0xc7, 0xcb, 0xc5, 0xc3, 0xcb, 0xc8,
+               0xc9, 0xc4, 0xce, 0xc3, 0xcf, 0xc2, 0xc5, 0xcc,
+               0xc2, 0xc9, 0xc8, 0xc5, 0xcc, 0xcf, 0xc3, 0xca,
+               0xc7, 0xcb, 0xc0, 0xce, 0xc4, 0xc1, 0xca, 0xc7,
+               0xc1, 0xc6, 0xcd, 0xc0, 0xcb, 0xc8, 0xc6, 0xcd,
+               0x7c, 0x7a, 0x71, 0x7f, 0x7a, 0x74, 0x7f, 0x72,
+               0x79, 0x77, 0x72, 0x7c, 0x76, 0x79, 0x78, 0x75,
+               0x70, 0x76, 0x7d, 0x71, 0x73, 0x7d, 0x74, 0x7e,
+               0x7e, 0x70, 0x77, 0x7b, 0x75, 0x73, 0x7b, 0x78,
+               0x79, 0x74, 0x7e, 0x73, 0x7f, 0x72, 0x75, 0x7c,
+               0x72, 0x79, 0x78, 0x75, 0x7c, 0x7f, 0x73, 0x7a,
+               0x77, 0x7b, 0x70, 0x7e, 0x74, 0x71, 0x7a, 0x77,
+               0x71, 0x76, 0x7d, 0x70, 0x7b, 0x78, 0x76, 0x7d,
+               0x4c, 0x4a, 0x41, 0x4f, 0x4a, 0x44, 0x4f, 0x42,
+               0x49, 0x47, 0x42, 0x4c, 0x46, 0x49, 0x48, 0x45,
+               0x40, 0x46, 0x4d, 0x41, 0x43, 0x4d, 0x44, 0x4e,
+               0x4e, 0x40, 0x47, 0x4b, 0x45, 0x43, 0x4b, 0x48,
+               0x49, 0x44, 0x4e, 0x43, 0x4f, 0x42, 0x45, 0x4c,
+               0x42, 0x49, 0x48, 0x45, 0x4c, 0x4f, 0x43, 0x4a,
+               0x47, 0x4b, 0x40, 0x4e, 0x44, 0x41, 0x4a, 0x47,
+               0x41, 0x46, 0x4d, 0x40, 0x4b, 0x48, 0x46, 0x4d,
+               0xac, 0xaa, 0xa1, 0xaf, 0xaa, 0xa4, 0xaf, 0xa2,
+               0xa9, 0xa7, 0xa2, 0xac, 0xa6, 0xa9, 0xa8, 0xa5,
+               0xa0, 0xa6, 0xad, 0xa1, 0xa3, 0xad, 0xa4, 0xae,
+               0xae, 0xa0, 0xa7, 0xab, 0xa5, 0xa3, 0xab, 0xa8,
+               0xa9, 0xa4, 0xae, 0xa3, 0xaf, 0xa2, 0xa5, 0xac,
+               0xa2, 0xa9, 0xa8, 0xa5, 0xac, 0xaf, 0xa3, 0xaa,
+               0xa7, 0xab, 0xa0, 0xae, 0xa4, 0xa1, 0xaa, 0xa7,
+               0xa1, 0xa6, 0xad, 0xa0, 0xab, 0xa8, 0xa6, 0xad,
+               0x7c, 0x7a, 0x71, 0x7f, 0x7a, 0x74, 0x7f, 0x72,
+               0x79, 0x77, 0x72, 0x7c, 0x76, 0x79, 0x78, 0x75,
+               0x70, 0x76, 0x7d, 0x71, 0x73, 0x7d, 0x74, 0x7e,
+               0x7e, 0x70, 0x77, 0x7b, 0x75, 0x73, 0x7b, 0x78,
+               0x79, 0x74, 0x7e, 0x73, 0x7f, 0x72, 0x75, 0x7c,
+               0x72, 0x79, 0x78, 0x75, 0x7c, 0x7f, 0x73, 0x7a,
+               0x77, 0x7b, 0x70, 0x7e, 0x74, 0x71, 0x7a, 0x77,
+               0x71, 0x76, 0x7d, 0x70, 0x7b, 0x78, 0x76, 0x7d,
+               0xbc, 0xba, 0xb1, 0xbf, 0xba, 0xb4, 0xbf, 0xb2,
+               0xb9, 0xb7, 0xb2, 0xbc, 0xb6, 0xb9, 0xb8, 0xb5,
+               0xb0, 0xb6, 0xbd, 0xb1, 0xb3, 0xbd, 0xb4, 0xbe,
+               0xbe, 0xb0, 0xb7, 0xbb, 0xb5, 0xb3, 0xbb, 0xb8,
+               0xb9, 0xb4, 0xbe, 0xb3, 0xbf, 0xb2, 0xb5, 0xbc,
+               0xb2, 0xb9, 0xb8, 0xb5, 0xbc, 0xbf, 0xb3, 0xba,
+               0xb7, 0xbb, 0xb0, 0xbe, 0xb4, 0xb1, 0xba, 0xb7,
+               0xb1, 0xb6, 0xbd, 0xb0, 0xbb, 0xb8, 0xb6, 0xbd,
+               0xdc, 0xda, 0xd1, 0xdf, 0xda, 0xd4, 0xdf, 0xd2,
+               0xd9, 0xd7, 0xd2, 0xdc, 0xd6, 0xd9, 0xd8, 0xd5,
+               0xd0, 0xd6, 0xdd, 0xd1, 0xd3, 0xdd, 0xd4, 0xde,
+               0xde, 0xd0, 0xd7, 0xdb, 0xd5, 0xd3, 0xdb, 0xd8,
+               0xd9, 0xd4, 0xde, 0xd3, 0xdf, 0xd2, 0xd5, 0xdc,
+               0xd2, 0xd9, 0xd8, 0xd5, 0xdc, 0xdf, 0xd3, 0xda,
+               0xd7, 0xdb, 0xd0, 0xde, 0xd4, 0xd1, 0xda, 0xd7,
+               0xd1, 0xd6, 0xdd, 0xd0, 0xdb, 0xd8, 0xd6, 0xdd,
+               0x6c, 0x6a, 0x61, 0x6f, 0x6a, 0x64, 0x6f, 0x62,
+               0x69, 0x67, 0x62, 0x6c, 0x66, 0x69, 0x68, 0x65,
+               0x60, 0x66, 0x6d, 0x61, 0x63, 0x6d, 0x64, 0x6e,
+               0x6e, 0x60, 0x67, 0x6b, 0x65, 0x63, 0x6b, 0x68,
+               0x69, 0x64, 0x6e, 0x63, 0x6f, 0x62, 0x65, 0x6c,
+               0x62, 0x69, 0x68, 0x65, 0x6c, 0x6f, 0x63, 0x6a,
+               0x67, 0x6b, 0x60, 0x6e, 0x64, 0x61, 0x6a, 0x67,
+               0x61, 0x66, 0x6d, 0x60, 0x6b, 0x68, 0x66, 0x6d,
+               0x1c, 0x1a, 0x11, 0x1f, 0x1a, 0x14, 0x1f, 0x12,
+               0x19, 0x17, 0x12, 0x1c, 0x16, 0x19, 0x18, 0x15,
+               0x10, 0x16, 0x1d, 0x11, 0x13, 0x1d, 0x14, 0x1e,
+               0x1e, 0x10, 0x17, 0x1b, 0x15, 0x13, 0x1b, 0x18,
+               0x19, 0x14, 0x1e, 0x13, 0x1f, 0x12, 0x15, 0x1c,
+               0x12, 0x19, 0x18, 0x15, 0x1c, 0x1f, 0x13, 0x1a,
+               0x17, 0x1b, 0x10, 0x1e, 0x14, 0x11, 0x1a, 0x17,
+               0x11, 0x16, 0x1d, 0x10, 0x1b, 0x18, 0x16, 0x1d,
+               0x8c, 0x8a, 0x81, 0x8f, 0x8a, 0x84, 0x8f, 0x82,
+               0x89, 0x87, 0x82, 0x8c, 0x86, 0x89, 0x88, 0x85,
+               0x80, 0x86, 0x8d, 0x81, 0x83, 0x8d, 0x84, 0x8e,
+               0x8e, 0x80, 0x87, 0x8b, 0x85, 0x83, 0x8b, 0x88,
+               0x89, 0x84, 0x8e, 0x83, 0x8f, 0x82, 0x85, 0x8c,
+               0x82, 0x89, 0x88, 0x85, 0x8c, 0x8f, 0x83, 0x8a,
+               0x87, 0x8b, 0x80, 0x8e, 0x84, 0x81, 0x8a, 0x87,
+               0x81, 0x86, 0x8d, 0x80, 0x8b, 0x88, 0x86, 0x8d,
+               0x5c, 0x5a, 0x51, 0x5f, 0x5a, 0x54, 0x5f, 0x52,
+               0x59, 0x57, 0x52, 0x5c, 0x56, 0x59, 0x58, 0x55,
+               0x50, 0x56, 0x5d, 0x51, 0x53, 0x5d, 0x54, 0x5e,
+               0x5e, 0x50, 0x57, 0x5b, 0x55, 0x53, 0x5b, 0x58,
+               0x59, 0x54, 0x5e, 0x53, 0x5f, 0x52, 0x55, 0x5c,
+               0x52, 0x59, 0x58, 0x55, 0x5c, 0x5f, 0x53, 0x5a,
+               0x57, 0x5b, 0x50, 0x5e, 0x54, 0x51, 0x5a, 0x57,
+               0x51, 0x56, 0x5d, 0x50, 0x5b, 0x58, 0x56, 0x5d,
+               0x5c, 0x5a, 0x51, 0x5f, 0x5a, 0x54, 0x5f, 0x52,
+               0x59, 0x57, 0x52, 0x5c, 0x56, 0x59, 0x58, 0x55,
+               0x50, 0x56, 0x5d, 0x51, 0x53, 0x5d, 0x54, 0x5e,
+               0x5e, 0x50, 0x57, 0x5b, 0x55, 0x53, 0x5b, 0x58,
+               0x59, 0x54, 0x5e, 0x53, 0x5f, 0x52, 0x55, 0x5c,
+               0x52, 0x59, 0x58, 0x55, 0x5c, 0x5f, 0x53, 0x5a,
+               0x57, 0x5b, 0x50, 0x5e, 0x54, 0x51, 0x5a, 0x57,
+               0x51, 0x56, 0x5d, 0x50, 0x5b, 0x58, 0x56, 0x5d,
+               0x0c, 0x0a, 0x01, 0x0f, 0x0a, 0x04, 0x0f, 0x02,
+               0x09, 0x07, 0x02, 0x0c, 0x06, 0x09, 0x08, 0x05,
+               0x00, 0x06, 0x0d, 0x01, 0x03, 0x0d, 0x04, 0x0e,
+               0x0e, 0x00, 0x07, 0x0b, 0x05, 0x03, 0x0b, 0x08,
+               0x09, 0x04, 0x0e, 0x03, 0x0f, 0x02, 0x05, 0x0c,
+               0x02, 0x09, 0x08, 0x05, 0x0c, 0x0f, 0x03, 0x0a,
+               0x07, 0x0b, 0x00, 0x0e, 0x04, 0x01, 0x0a, 0x07,
+               0x01, 0x06, 0x0d, 0x00, 0x0b, 0x08, 0x06, 0x0d,
+               0x3c, 0x3a, 0x31, 0x3f, 0x3a, 0x34, 0x3f, 0x32,
+               0x39, 0x37, 0x32, 0x3c, 0x36, 0x39, 0x38, 0x35,
+               0x30, 0x36, 0x3d, 0x31, 0x33, 0x3d, 0x34, 0x3e,
+               0x3e, 0x30, 0x37, 0x3b, 0x35, 0x33, 0x3b, 0x38,
+               0x39, 0x34, 0x3e, 0x33, 0x3f, 0x32, 0x35, 0x3c,
+               0x32, 0x39, 0x38, 0x35, 0x3c, 0x3f, 0x33, 0x3a,
+               0x37, 0x3b, 0x30, 0x3e, 0x34, 0x31, 0x3a, 0x37,
+               0x31, 0x36, 0x3d, 0x30, 0x3b, 0x38, 0x36, 0x3d,
+               0xfc, 0xfa, 0xf1, 0xff, 0xfa, 0xf4, 0xff, 0xf2,
+               0xf9, 0xf7, 0xf2, 0xfc, 0xf6, 0xf9, 0xf8, 0xf5,
+               0xf0, 0xf6, 0xfd, 0xf1, 0xf3, 0xfd, 0xf4, 0xfe,
+               0xfe, 0xf0, 0xf7, 0xfb, 0xf5, 0xf3, 0xfb, 0xf8,
+               0xf9, 0xf4, 0xfe, 0xf3, 0xff, 0xf2, 0xf5, 0xfc,
+               0xf2, 0xf9, 0xf8, 0xf5, 0xfc, 0xff, 0xf3, 0xfa,
+               0xf7, 0xfb, 0xf0, 0xfe, 0xf4, 0xf1, 0xfa, 0xf7,
+               0xf1, 0xf6, 0xfd, 0xf0, 0xfb, 0xf8, 0xf6, 0xfd,
+               0xfc, 0xfa, 0xf1, 0xff, 0xfa, 0xf4, 0xff, 0xf2,
+               0xf9, 0xf7, 0xf2, 0xfc, 0xf6, 0xf9, 0xf8, 0xf5,
+               0xf0, 0xf6, 0xfd, 0xf1, 0xf3, 0xfd, 0xf4, 0xfe,
+               0xfe, 0xf0, 0xf7, 0xfb, 0xf5, 0xf3, 0xfb, 0xf8,
+               0xf9, 0xf4, 0xfe, 0xf3, 0xff, 0xf2, 0xf5, 0xfc,
+               0xf2, 0xf9, 0xf8, 0xf5, 0xfc, 0xff, 0xf3, 0xfa,
+               0xf7, 0xfb, 0xf0, 0xfe, 0xf4, 0xf1, 0xfa, 0xf7,
+               0xf1, 0xf6, 0xfd, 0xf0, 0xfb, 0xf8, 0xf6, 0xfd,
+               0xac, 0xaa, 0xa1, 0xaf, 0xaa, 0xa4, 0xaf, 0xa2,
+               0xa9, 0xa7, 0xa2, 0xac, 0xa6, 0xa9, 0xa8, 0xa5,
+               0xa0, 0xa6, 0xad, 0xa1, 0xa3, 0xad, 0xa4, 0xae,
+               0xae, 0xa0, 0xa7, 0xab, 0xa5, 0xa3, 0xab, 0xa8,
+               0xa9, 0xa4, 0xae, 0xa3, 0xaf, 0xa2, 0xa5, 0xac,
+               0xa2, 0xa9, 0xa8, 0xa5, 0xac, 0xaf, 0xa3, 0xaa,
+               0xa7, 0xab, 0xa0, 0xae, 0xa4, 0xa1, 0xaa, 0xa7,
+               0xa1, 0xa6, 0xad, 0xa0, 0xab, 0xa8, 0xa6, 0xad,
+               0xdc, 0xda, 0xd1, 0xdf, 0xda, 0xd4, 0xdf, 0xd2,
+               0xd9, 0xd7, 0xd2, 0xdc, 0xd6, 0xd9, 0xd8, 0xd5,
+               0xd0, 0xd6, 0xdd, 0xd1, 0xd3, 0xdd, 0xd4, 0xde,
+               0xde, 0xd0, 0xd7, 0xdb, 0xd5, 0xd3, 0xdb, 0xd8,
+               0xd9, 0xd4, 0xde, 0xd3, 0xdf, 0xd2, 0xd5, 0xdc,
+               0xd2, 0xd9, 0xd8, 0xd5, 0xdc, 0xdf, 0xd3, 0xda,
+               0xd7, 0xdb, 0xd0, 0xde, 0xd4, 0xd1, 0xda, 0xd7,
+               0xd1, 0xd6, 0xdd, 0xd0, 0xdb, 0xd8, 0xd6, 0xdd,
+               0x3c, 0x3a, 0x31, 0x3f, 0x3a, 0x34, 0x3f, 0x32,
+               0x39, 0x37, 0x32, 0x3c, 0x36, 0x39, 0x38, 0x35,
+               0x30, 0x36, 0x3d, 0x31, 0x33, 0x3d, 0x34, 0x3e,
+               0x3e, 0x30, 0x37, 0x3b, 0x35, 0x33, 0x3b, 0x38,
+               0x39, 0x34, 0x3e, 0x33, 0x3f, 0x32, 0x35, 0x3c,
+               0x32, 0x39, 0x38, 0x35, 0x3c, 0x3f, 0x33, 0x3a,
+               0x37, 0x3b, 0x30, 0x3e, 0x34, 0x31, 0x3a, 0x37,
+               0x31, 0x36, 0x3d, 0x30, 0x3b, 0x38, 0x36, 0x3d,
+               0x0c, 0x0a, 0x01, 0x0f, 0x0a, 0x04, 0x0f, 0x02,
+               0x09, 0x07, 0x02, 0x0c, 0x06, 0x09, 0x08, 0x05,
+               0x00, 0x06, 0x0d, 0x01, 0x03, 0x0d, 0x04, 0x0e,
+               0x0e, 0x00, 0x07, 0x0b, 0x05, 0x03, 0x0b, 0x08,
+               0x09, 0x04, 0x0e, 0x03, 0x0f, 0x02, 0x05, 0x0c,
+               0x02, 0x09, 0x08, 0x05, 0x0c, 0x0f, 0x03, 0x0a,
+               0x07, 0x0b, 0x00, 0x0e, 0x04, 0x01, 0x0a, 0x07,
+               0x01, 0x06, 0x0d, 0x00, 0x0b, 0x08, 0x06, 0x0d,
+               0x9c, 0x9a, 0x91, 0x9f, 0x9a, 0x94, 0x9f, 0x92,
+               0x99, 0x97, 0x92, 0x9c, 0x96, 0x99, 0x98, 0x95,
+               0x90, 0x96, 0x9d, 0x91, 0x93, 0x9d, 0x94, 0x9e,
+               0x9e, 0x90, 0x97, 0x9b, 0x95, 0x93, 0x9b, 0x98,
+               0x99, 0x94, 0x9e, 0x93, 0x9f, 0x92, 0x95, 0x9c,
+               0x92, 0x99, 0x98, 0x95, 0x9c, 0x9f, 0x93, 0x9a,
+               0x97, 0x9b, 0x90, 0x9e, 0x94, 0x91, 0x9a, 0x97,
+               0x91, 0x96, 0x9d, 0x90, 0x9b, 0x98, 0x96, 0x9d,
+               0xec, 0xea, 0xe1, 0xef, 0xea, 0xe4, 0xef, 0xe2,
+               0xe9, 0xe7, 0xe2, 0xec, 0xe6, 0xe9, 0xe8, 0xe5,
+               0xe0, 0xe6, 0xed, 0xe1, 0xe3, 0xed, 0xe4, 0xee,
+               0xee, 0xe0, 0xe7, 0xeb, 0xe5, 0xe3, 0xeb, 0xe8,
+               0xe9, 0xe4, 0xee, 0xe3, 0xef, 0xe2, 0xe5, 0xec,
+               0xe2, 0xe9, 0xe8, 0xe5, 0xec, 0xef, 0xe3, 0xea,
+               0xe7, 0xeb, 0xe0, 0xee, 0xe4, 0xe1, 0xea, 0xe7,
+               0xe1, 0xe6, 0xed, 0xe0, 0xeb, 0xe8, 0xe6, 0xed,
+               0x8c, 0x8a, 0x81, 0x8f, 0x8a, 0x84, 0x8f, 0x82,
+               0x89, 0x87, 0x82, 0x8c, 0x86, 0x89, 0x88, 0x85,
+               0x80, 0x86, 0x8d, 0x81, 0x83, 0x8d, 0x84, 0x8e,
+               0x8e, 0x80, 0x87, 0x8b, 0x85, 0x83, 0x8b, 0x88,
+               0x89, 0x84, 0x8e, 0x83, 0x8f, 0x82, 0x85, 0x8c,
+               0x82, 0x89, 0x88, 0x85, 0x8c, 0x8f, 0x83, 0x8a,
+               0x87, 0x8b, 0x80, 0x8e, 0x84, 0x81, 0x8a, 0x87,
+               0x81, 0x86, 0x8d, 0x80, 0x8b, 0x88, 0x86, 0x8d,
+               0x9c, 0x9a, 0x91, 0x9f, 0x9a, 0x94, 0x9f, 0x92,
+               0x99, 0x97, 0x92, 0x9c, 0x96, 0x99, 0x98, 0x95,
+               0x90, 0x96, 0x9d, 0x91, 0x93, 0x9d, 0x94, 0x9e,
+               0x9e, 0x90, 0x97, 0x9b, 0x95, 0x93, 0x9b, 0x98,
+               0x99, 0x94, 0x9e, 0x93, 0x9f, 0x92, 0x95, 0x9c,
+               0x92, 0x99, 0x98, 0x95, 0x9c, 0x9f, 0x93, 0x9a,
+               0x97, 0x9b, 0x90, 0x9e, 0x94, 0x91, 0x9a, 0x97,
+               0x91, 0x96, 0x9d, 0x90, 0x9b, 0x98, 0x96, 0x9d,
+               0x6c, 0x6a, 0x61, 0x6f, 0x6a, 0x64, 0x6f, 0x62,
+               0x69, 0x67, 0x62, 0x6c, 0x66, 0x69, 0x68, 0x65,
+               0x60, 0x66, 0x6d, 0x61, 0x63, 0x6d, 0x64, 0x6e,
+               0x6e, 0x60, 0x67, 0x6b, 0x65, 0x63, 0x6b, 0x68,
+               0x69, 0x64, 0x6e, 0x63, 0x6f, 0x62, 0x65, 0x6c,
+               0x62, 0x69, 0x68, 0x65, 0x6c, 0x6f, 0x63, 0x6a,
+               0x67, 0x6b, 0x60, 0x6e, 0x64, 0x61, 0x6a, 0x67,
+               0x61, 0x66, 0x6d, 0x60, 0x6b, 0x68, 0x66, 0x6d,
+               0x4c, 0x4a, 0x41, 0x4f, 0x4a, 0x44, 0x4f, 0x42,
+               0x49, 0x47, 0x42, 0x4c, 0x46, 0x49, 0x48, 0x45,
+               0x40, 0x46, 0x4d, 0x41, 0x43, 0x4d, 0x44, 0x4e,
+               0x4e, 0x40, 0x47, 0x4b, 0x45, 0x43, 0x4b, 0x48,
+               0x49, 0x44, 0x4e, 0x43, 0x4f, 0x42, 0x45, 0x4c,
+               0x42, 0x49, 0x48, 0x45, 0x4c, 0x4f, 0x43, 0x4a,
+               0x47, 0x4b, 0x40, 0x4e, 0x44, 0x41, 0x4a, 0x47,
+               0x41, 0x46, 0x4d, 0x40, 0x4b, 0x48, 0x46, 0x4d,
+               0xbc, 0xba, 0xb1, 0xbf, 0xba, 0xb4, 0xbf, 0xb2,
+               0xb9, 0xb7, 0xb2, 0xbc, 0xb6, 0xb9, 0xb8, 0xb5,
+               0xb0, 0xb6, 0xbd, 0xb1, 0xb3, 0xbd, 0xb4, 0xbe,
+               0xbe, 0xb0, 0xb7, 0xbb, 0xb5, 0xb3, 0xbb, 0xb8,
+               0xb9, 0xb4, 0xbe, 0xb3, 0xbf, 0xb2, 0xb5, 0xbc,
+               0xb2, 0xb9, 0xb8, 0xb5, 0xbc, 0xbf, 0xb3, 0xba,
+               0xb7, 0xbb, 0xb0, 0xbe, 0xb4, 0xb1, 0xba, 0xb7,
+               0xb1, 0xb6, 0xbd, 0xb0, 0xbb, 0xb8, 0xb6, 0xbd,
+               0x2c, 0x2a, 0x21, 0x2f, 0x2a, 0x24, 0x2f, 0x22,
+               0x29, 0x27, 0x22, 0x2c, 0x26, 0x29, 0x28, 0x25,
+               0x20, 0x26, 0x2d, 0x21, 0x23, 0x2d, 0x24, 0x2e,
+               0x2e, 0x20, 0x27, 0x2b, 0x25, 0x23, 0x2b, 0x28,
+               0x29, 0x24, 0x2e, 0x23, 0x2f, 0x22, 0x25, 0x2c,
+               0x22, 0x29, 0x28, 0x25, 0x2c, 0x2f, 0x23, 0x2a,
+               0x27, 0x2b, 0x20, 0x2e, 0x24, 0x21, 0x2a, 0x27,
+               0x21, 0x26, 0x2d, 0x20, 0x2b, 0x28, 0x26, 0x2d,
+               0x8c, 0x8a, 0x81, 0x8f, 0x8a, 0x84, 0x8f, 0x82,
+               0x89, 0x87, 0x82, 0x8c, 0x86, 0x89, 0x88, 0x85,
+               0x80, 0x86, 0x8d, 0x81, 0x83, 0x8d, 0x84, 0x8e,
+               0x8e, 0x80, 0x87, 0x8b, 0x85, 0x83, 0x8b, 0x88,
+               0x89, 0x84, 0x8e, 0x83, 0x8f, 0x82, 0x85, 0x8c,
+               0x82, 0x89, 0x88, 0x85, 0x8c, 0x8f, 0x83, 0x8a,
+               0x87, 0x8b, 0x80, 0x8e, 0x84, 0x81, 0x8a, 0x87,
+               0x81, 0x86, 0x8d, 0x80, 0x8b, 0x88, 0x86, 0x8d,
+               0x1c, 0x1a, 0x11, 0x1f, 0x1a, 0x14, 0x1f, 0x12,
+               0x19, 0x17, 0x12, 0x1c, 0x16, 0x19, 0x18, 0x15,
+               0x10, 0x16, 0x1d, 0x11, 0x13, 0x1d, 0x14, 0x1e,
+               0x1e, 0x10, 0x17, 0x1b, 0x15, 0x13, 0x1b, 0x18,
+               0x19, 0x14, 0x1e, 0x13, 0x1f, 0x12, 0x15, 0x1c,
+               0x12, 0x19, 0x18, 0x15, 0x1c, 0x1f, 0x13, 0x1a,
+               0x17, 0x1b, 0x10, 0x1e, 0x14, 0x11, 0x1a, 0x17,
+               0x11, 0x16, 0x1d, 0x10, 0x1b, 0x18, 0x16, 0x1d,
+               0xcc, 0xca, 0xc1, 0xcf, 0xca, 0xc4, 0xcf, 0xc2,
+               0xc9, 0xc7, 0xc2, 0xcc, 0xc6, 0xc9, 0xc8, 0xc5,
+               0xc0, 0xc6, 0xcd, 0xc1, 0xc3, 0xcd, 0xc4, 0xce,
+               0xce, 0xc0, 0xc7, 0xcb, 0xc5, 0xc3, 0xcb, 0xc8,
+               0xc9, 0xc4, 0xce, 0xc3, 0xcf, 0xc2, 0xc5, 0xcc,
+               0xc2, 0xc9, 0xc8, 0xc5, 0xcc, 0xcf, 0xc3, 0xca,
+               0xc7, 0xcb, 0xc0, 0xce, 0xc4, 0xc1, 0xca, 0xc7,
+               0xc1, 0xc6, 0xcd, 0xc0, 0xcb, 0xc8, 0xc6, 0xcd,
+               0xbc, 0xba, 0xb1, 0xbf, 0xba, 0xb4, 0xbf, 0xb2,
+               0xb9, 0xb7, 0xb2, 0xbc, 0xb6, 0xb9, 0xb8, 0xb5,
+               0xb0, 0xb6, 0xbd, 0xb1, 0xb3, 0xbd, 0xb4, 0xbe,
+               0xbe, 0xb0, 0xb7, 0xbb, 0xb5, 0xb3, 0xbb, 0xb8,
+               0xb9, 0xb4, 0xbe, 0xb3, 0xbf, 0xb2, 0xb5, 0xbc,
+               0xb2, 0xb9, 0xb8, 0xb5, 0xbc, 0xbf, 0xb3, 0xba,
+               0xb7, 0xbb, 0xb0, 0xbe, 0xb4, 0xb1, 0xba, 0xb7,
+               0xb1, 0xb6, 0xbd, 0xb0, 0xbb, 0xb8, 0xb6, 0xbd,
+               0x7c, 0x7a, 0x71, 0x7f, 0x7a, 0x74, 0x7f, 0x72,
+               0x79, 0x77, 0x72, 0x7c, 0x76, 0x79, 0x78, 0x75,
+               0x70, 0x76, 0x7d, 0x71, 0x73, 0x7d, 0x74, 0x7e,
+               0x7e, 0x70, 0x77, 0x7b, 0x75, 0x73, 0x7b, 0x78,
+               0x79, 0x74, 0x7e, 0x73, 0x7f, 0x72, 0x75, 0x7c,
+               0x72, 0x79, 0x78, 0x75, 0x7c, 0x7f, 0x73, 0x7a,
+               0x77, 0x7b, 0x70, 0x7e, 0x74, 0x71, 0x7a, 0x77,
+               0x71, 0x76, 0x7d, 0x70, 0x7b, 0x78, 0x76, 0x7d,
+               0xac, 0xaa, 0xa1, 0xaf, 0xaa, 0xa4, 0xaf, 0xa2,
+               0xa9, 0xa7, 0xa2, 0xac, 0xa6, 0xa9, 0xa8, 0xa5,
+               0xa0, 0xa6, 0xad, 0xa1, 0xa3, 0xad, 0xa4, 0xae,
+               0xae, 0xa0, 0xa7, 0xab, 0xa5, 0xa3, 0xab, 0xa8,
+               0xa9, 0xa4, 0xae, 0xa3, 0xaf, 0xa2, 0xa5, 0xac,
+               0xa2, 0xa9, 0xa8, 0xa5, 0xac, 0xaf, 0xa3, 0xaa,
+               0xa7, 0xab, 0xa0, 0xae, 0xa4, 0xa1, 0xaa, 0xa7,
+               0xa1, 0xa6, 0xad, 0xa0, 0xab, 0xa8, 0xa6, 0xad,
+               0x1c, 0x1a, 0x11, 0x1f, 0x1a, 0x14, 0x1f, 0x12,
+               0x19, 0x17, 0x12, 0x1c, 0x16, 0x19, 0x18, 0x15,
+               0x10, 0x16, 0x1d, 0x11, 0x13, 0x1d, 0x14, 0x1e,
+               0x1e, 0x10, 0x17, 0x1b, 0x15, 0x13, 0x1b, 0x18,
+               0x19, 0x14, 0x1e, 0x13, 0x1f, 0x12, 0x15, 0x1c,
+               0x12, 0x19, 0x18, 0x15, 0x1c, 0x1f, 0x13, 0x1a,
+               0x17, 0x1b, 0x10, 0x1e, 0x14, 0x11, 0x1a, 0x17,
+               0x11, 0x16, 0x1d, 0x10, 0x1b, 0x18, 0x16, 0x1d,
+               0xdc, 0xda, 0xd1, 0xdf, 0xda, 0xd4, 0xdf, 0xd2,
+               0xd9, 0xd7, 0xd2, 0xdc, 0xd6, 0xd9, 0xd8, 0xd5,
+               0xd0, 0xd6, 0xdd, 0xd1, 0xd3, 0xdd, 0xd4, 0xde,
+               0xde, 0xd0, 0xd7, 0xdb, 0xd5, 0xd3, 0xdb, 0xd8,
+               0xd9, 0xd4, 0xde, 0xd3, 0xdf, 0xd2, 0xd5, 0xdc,
+               0xd2, 0xd9, 0xd8, 0xd5, 0xdc, 0xdf, 0xd3, 0xda,
+               0xd7, 0xdb, 0xd0, 0xde, 0xd4, 0xd1, 0xda, 0xd7,
+               0xd1, 0xd6, 0xdd, 0xd0, 0xdb, 0xd8, 0xd6, 0xdd,
+               0xec, 0xea, 0xe1, 0xef, 0xea, 0xe4, 0xef, 0xe2,
+               0xe9, 0xe7, 0xe2, 0xec, 0xe6, 0xe9, 0xe8, 0xe5,
+               0xe0, 0xe6, 0xed, 0xe1, 0xe3, 0xed, 0xe4, 0xee,
+               0xee, 0xe0, 0xe7, 0xeb, 0xe5, 0xe3, 0xeb, 0xe8,
+               0xe9, 0xe4, 0xee, 0xe3, 0xef, 0xe2, 0xe5, 0xec,
+               0xe2, 0xe9, 0xe8, 0xe5, 0xec, 0xef, 0xe3, 0xea,
+               0xe7, 0xeb, 0xe0, 0xee, 0xe4, 0xe1, 0xea, 0xe7,
+               0xe1, 0xe6, 0xed, 0xe0, 0xeb, 0xe8, 0xe6, 0xed,
+               0x7c, 0x7a, 0x71, 0x7f, 0x7a, 0x74, 0x7f, 0x72,
+               0x79, 0x77, 0x72, 0x7c, 0x76, 0x79, 0x78, 0x75,
+               0x70, 0x76, 0x7d, 0x71, 0x73, 0x7d, 0x74, 0x7e,
+               0x7e, 0x70, 0x77, 0x7b, 0x75, 0x73, 0x7b, 0x78,
+               0x79, 0x74, 0x7e, 0x73, 0x7f, 0x72, 0x75, 0x7c,
+               0x72, 0x79, 0x78, 0x75, 0x7c, 0x7f, 0x73, 0x7a,
+               0x77, 0x7b, 0x70, 0x7e, 0x74, 0x71, 0x7a, 0x77,
+               0x71, 0x76, 0x7d, 0x70, 0x7b, 0x78, 0x76, 0x7d,
+               0x2c, 0x2a, 0x21, 0x2f, 0x2a, 0x24, 0x2f, 0x22,
+               0x29, 0x27, 0x22, 0x2c, 0x26, 0x29, 0x28, 0x25,
+               0x20, 0x26, 0x2d, 0x21, 0x23, 0x2d, 0x24, 0x2e,
+               0x2e, 0x20, 0x27, 0x2b, 0x25, 0x23, 0x2b, 0x28,
+               0x29, 0x24, 0x2e, 0x23, 0x2f, 0x22, 0x25, 0x2c,
+               0x22, 0x29, 0x28, 0x25, 0x2c, 0x2f, 0x23, 0x2a,
+               0x27, 0x2b, 0x20, 0x2e, 0x24, 0x21, 0x2a, 0x27,
+               0x21, 0x26, 0x2d, 0x20, 0x2b, 0x28, 0x26, 0x2d,
+               0x8c, 0x8a, 0x81, 0x8f, 0x8a, 0x84, 0x8f, 0x82,
+               0x89, 0x87, 0x82, 0x8c, 0x86, 0x89, 0x88, 0x85,
+               0x80, 0x86, 0x8d, 0x81, 0x83, 0x8d, 0x84, 0x8e,
+               0x8e, 0x80, 0x87, 0x8b, 0x85, 0x83, 0x8b, 0x88,
+               0x89, 0x84, 0x8e, 0x83, 0x8f, 0x82, 0x85, 0x8c,
+               0x82, 0x89, 0x88, 0x85, 0x8c, 0x8f, 0x83, 0x8a,
+               0x87, 0x8b, 0x80, 0x8e, 0x84, 0x81, 0x8a, 0x87,
+               0x81, 0x86, 0x8d, 0x80, 0x8b, 0x88, 0x86, 0x8d,
+               0xdc, 0xda, 0xd1, 0xdf, 0xda, 0xd4, 0xdf, 0xd2,
+               0xd9, 0xd7, 0xd2, 0xdc, 0xd6, 0xd9, 0xd8, 0xd5,
+               0xd0, 0xd6, 0xdd, 0xd1, 0xd3, 0xdd, 0xd4, 0xde,
+               0xde, 0xd0, 0xd7, 0xdb, 0xd5, 0xd3, 0xdb, 0xd8,
+               0xd9, 0xd4, 0xde, 0xd3, 0xdf, 0xd2, 0xd5, 0xdc,
+               0xd2, 0xd9, 0xd8, 0xd5, 0xdc, 0xdf, 0xd3, 0xda,
+               0xd7, 0xdb, 0xd0, 0xde, 0xd4, 0xd1, 0xda, 0xd7,
+               0xd1, 0xd6, 0xdd, 0xd0, 0xdb, 0xd8, 0xd6, 0xdd,
+               0xfc, 0xfa, 0xf1, 0xff, 0xfa, 0xf4, 0xff, 0xf2,
+               0xf9, 0xf7, 0xf2, 0xfc, 0xf6, 0xf9, 0xf8, 0xf5,
+               0xf0, 0xf6, 0xfd, 0xf1, 0xf3, 0xfd, 0xf4, 0xfe,
+               0xfe, 0xf0, 0xf7, 0xfb, 0xf5, 0xf3, 0xfb, 0xf8,
+               0xf9, 0xf4, 0xfe, 0xf3, 0xff, 0xf2, 0xf5, 0xfc,
+               0xf2, 0xf9, 0xf8, 0xf5, 0xfc, 0xff, 0xf3, 0xfa,
+               0xf7, 0xfb, 0xf0, 0xfe, 0xf4, 0xf1, 0xfa, 0xf7,
+               0xf1, 0xf6, 0xfd, 0xf0, 0xfb, 0xf8, 0xf6, 0xfd,
+               0x6c, 0x6a, 0x61, 0x6f, 0x6a, 0x64, 0x6f, 0x62,
+               0x69, 0x67, 0x62, 0x6c, 0x66, 0x69, 0x68, 0x65,
+               0x60, 0x66, 0x6d, 0x61, 0x63, 0x6d, 0x64, 0x6e,
+               0x6e, 0x60, 0x67, 0x6b, 0x65, 0x63, 0x6b, 0x68,
+               0x69, 0x64, 0x6e, 0x63, 0x6f, 0x62, 0x65, 0x6c,
+               0x62, 0x69, 0x68, 0x65, 0x6c, 0x6f, 0x63, 0x6a,
+               0x67, 0x6b, 0x60, 0x6e, 0x64, 0x61, 0x6a, 0x67,
+               0x61, 0x66, 0x6d, 0x60, 0x6b, 0x68, 0x66, 0x6d,
+               0x9c, 0x9a, 0x91, 0x9f, 0x9a, 0x94, 0x9f, 0x92,
+               0x99, 0x97, 0x92, 0x9c, 0x96, 0x99, 0x98, 0x95,
+               0x90, 0x96, 0x9d, 0x91, 0x93, 0x9d, 0x94, 0x9e,
+               0x9e, 0x90, 0x97, 0x9b, 0x95, 0x93, 0x9b, 0x98,
+               0x99, 0x94, 0x9e, 0x93, 0x9f, 0x92, 0x95, 0x9c,
+               0x92, 0x99, 0x98, 0x95, 0x9c, 0x9f, 0x93, 0x9a,
+               0x97, 0x9b, 0x90, 0x9e, 0x94, 0x91, 0x9a, 0x97,
+               0x91, 0x96, 0x9d, 0x90, 0x9b, 0x98, 0x96, 0x9d,
+               0xfc, 0xfa, 0xf1, 0xff, 0xfa, 0xf4, 0xff, 0xf2,
+               0xf9, 0xf7, 0xf2, 0xfc, 0xf6, 0xf9, 0xf8, 0xf5,
+               0xf0, 0xf6, 0xfd, 0xf1, 0xf3, 0xfd, 0xf4, 0xfe,
+               0xfe, 0xf0, 0xf7, 0xfb, 0xf5, 0xf3, 0xfb, 0xf8,
+               0xf9, 0xf4, 0xfe, 0xf3, 0xff, 0xf2, 0xf5, 0xfc,
+               0xf2, 0xf9, 0xf8, 0xf5, 0xfc, 0xff, 0xf3, 0xfa,
+               0xf7, 0xfb, 0xf0, 0xfe, 0xf4, 0xf1, 0xfa, 0xf7,
+               0xf1, 0xf6, 0xfd, 0xf0, 0xfb, 0xf8, 0xf6, 0xfd,
+               0xcc, 0xca, 0xc1, 0xcf, 0xca, 0xc4, 0xcf, 0xc2,
+               0xc9, 0xc7, 0xc2, 0xcc, 0xc6, 0xc9, 0xc8, 0xc5,
+               0xc0, 0xc6, 0xcd, 0xc1, 0xc3, 0xcd, 0xc4, 0xce,
+               0xce, 0xc0, 0xc7, 0xcb, 0xc5, 0xc3, 0xcb, 0xc8,
+               0xc9, 0xc4, 0xce, 0xc3, 0xcf, 0xc2, 0xc5, 0xcc,
+               0xc2, 0xc9, 0xc8, 0xc5, 0xcc, 0xcf, 0xc3, 0xca,
+               0xc7, 0xcb, 0xc0, 0xce, 0xc4, 0xc1, 0xca, 0xc7,
+               0xc1, 0xc6, 0xcd, 0xc0, 0xcb, 0xc8, 0xc6, 0xcd,
+               0x0c, 0x0a, 0x01, 0x0f, 0x0a, 0x04, 0x0f, 0x02,
+               0x09, 0x07, 0x02, 0x0c, 0x06, 0x09, 0x08, 0x05,
+               0x00, 0x06, 0x0d, 0x01, 0x03, 0x0d, 0x04, 0x0e,
+               0x0e, 0x00, 0x07, 0x0b, 0x05, 0x03, 0x0b, 0x08,
+               0x09, 0x04, 0x0e, 0x03, 0x0f, 0x02, 0x05, 0x0c,
+               0x02, 0x09, 0x08, 0x05, 0x0c, 0x0f, 0x03, 0x0a,
+               0x07, 0x0b, 0x00, 0x0e, 0x04, 0x01, 0x0a, 0x07,
+               0x01, 0x06, 0x0d, 0x00, 0x0b, 0x08, 0x06, 0x0d,
+               0x5c, 0x5a, 0x51, 0x5f, 0x5a, 0x54, 0x5f, 0x52,
+               0x59, 0x57, 0x52, 0x5c, 0x56, 0x59, 0x58, 0x55,
+               0x50, 0x56, 0x5d, 0x51, 0x53, 0x5d, 0x54, 0x5e,
+               0x5e, 0x50, 0x57, 0x5b, 0x55, 0x53, 0x5b, 0x58,
+               0x59, 0x54, 0x5e, 0x53, 0x5f, 0x52, 0x55, 0x5c,
+               0x52, 0x59, 0x58, 0x55, 0x5c, 0x5f, 0x53, 0x5a,
+               0x57, 0x5b, 0x50, 0x5e, 0x54, 0x51, 0x5a, 0x57,
+               0x51, 0x56, 0x5d, 0x50, 0x5b, 0x58, 0x56, 0x5d,
+               0x9c, 0x9a, 0x91, 0x9f, 0x9a, 0x94, 0x9f, 0x92,
+               0x99, 0x97, 0x92, 0x9c, 0x96, 0x99, 0x98, 0x95,
+               0x90, 0x96, 0x9d, 0x91, 0x93, 0x9d, 0x94, 0x9e,
+               0x9e, 0x90, 0x97, 0x9b, 0x95, 0x93, 0x9b, 0x98,
+               0x99, 0x94, 0x9e, 0x93, 0x9f, 0x92, 0x95, 0x9c,
+               0x92, 0x99, 0x98, 0x95, 0x9c, 0x9f, 0x93, 0x9a,
+               0x97, 0x9b, 0x90, 0x9e, 0x94, 0x91, 0x9a, 0x97,
+               0x91, 0x96, 0x9d, 0x90, 0x9b, 0x98, 0x96, 0x9d,
+               0x6c, 0x6a, 0x61, 0x6f, 0x6a, 0x64, 0x6f, 0x62,
+               0x69, 0x67, 0x62, 0x6c, 0x66, 0x69, 0x68, 0x65,
+               0x60, 0x66, 0x6d, 0x61, 0x63, 0x6d, 0x64, 0x6e,
+               0x6e, 0x60, 0x67, 0x6b, 0x65, 0x63, 0x6b, 0x68,
+               0x69, 0x64, 0x6e, 0x63, 0x6f, 0x62, 0x65, 0x6c,
+               0x62, 0x69, 0x68, 0x65, 0x6c, 0x6f, 0x63, 0x6a,
+               0x67, 0x6b, 0x60, 0x6e, 0x64, 0x61, 0x6a, 0x67,
+               0x61, 0x66, 0x6d, 0x60, 0x6b, 0x68, 0x66, 0x6d,
+               0xac, 0xaa, 0xa1, 0xaf, 0xaa, 0xa4, 0xaf, 0xa2,
+               0xa9, 0xa7, 0xa2, 0xac, 0xa6, 0xa9, 0xa8, 0xa5,
+               0xa0, 0xa6, 0xad, 0xa1, 0xa3, 0xad, 0xa4, 0xae,
+               0xae, 0xa0, 0xa7, 0xab, 0xa5, 0xa3, 0xab, 0xa8,
+               0xa9, 0xa4, 0xae, 0xa3, 0xaf, 0xa2, 0xa5, 0xac,
+               0xa2, 0xa9, 0xa8, 0xa5, 0xac, 0xaf, 0xa3, 0xaa,
+               0xa7, 0xab, 0xa0, 0xae, 0xa4, 0xa1, 0xaa, 0xa7,
+               0xa1, 0xa6, 0xad, 0xa0, 0xab, 0xa8, 0xa6, 0xad,
+               0x3c, 0x3a, 0x31, 0x3f, 0x3a, 0x34, 0x3f, 0x32,
+               0x39, 0x37, 0x32, 0x3c, 0x36, 0x39, 0x38, 0x35,
+               0x30, 0x36, 0x3d, 0x31, 0x33, 0x3d, 0x34, 0x3e,
+               0x3e, 0x30, 0x37, 0x3b, 0x35, 0x33, 0x3b, 0x38,
+               0x39, 0x34, 0x3e, 0x33, 0x3f, 0x32, 0x35, 0x3c,
+               0x32, 0x39, 0x38, 0x35, 0x3c, 0x3f, 0x33, 0x3a,
+               0x37, 0x3b, 0x30, 0x3e, 0x34, 0x31, 0x3a, 0x37,
+               0x31, 0x36, 0x3d, 0x30, 0x3b, 0x38, 0x36, 0x3d,
+               0x4c, 0x4a, 0x41, 0x4f, 0x4a, 0x44, 0x4f, 0x42,
+               0x49, 0x47, 0x42, 0x4c, 0x46, 0x49, 0x48, 0x45,
+               0x40, 0x46, 0x4d, 0x41, 0x43, 0x4d, 0x44, 0x4e,
+               0x4e, 0x40, 0x47, 0x4b, 0x45, 0x43, 0x4b, 0x48,
+               0x49, 0x44, 0x4e, 0x43, 0x4f, 0x42, 0x45, 0x4c,
+               0x42, 0x49, 0x48, 0x45, 0x4c, 0x4f, 0x43, 0x4a,
+               0x47, 0x4b, 0x40, 0x4e, 0x44, 0x41, 0x4a, 0x47,
+               0x41, 0x46, 0x4d, 0x40, 0x4b, 0x48, 0x46, 0x4d,
+               0x0c, 0x0a, 0x01, 0x0f, 0x0a, 0x04, 0x0f, 0x02,
+               0x09, 0x07, 0x02, 0x0c, 0x06, 0x09, 0x08, 0x05,
+               0x00, 0x06, 0x0d, 0x01, 0x03, 0x0d, 0x04, 0x0e,
+               0x0e, 0x00, 0x07, 0x0b, 0x05, 0x03, 0x0b, 0x08,
+               0x09, 0x04, 0x0e, 0x03, 0x0f, 0x02, 0x05, 0x0c,
+               0x02, 0x09, 0x08, 0x05, 0x0c, 0x0f, 0x03, 0x0a,
+               0x07, 0x0b, 0x00, 0x0e, 0x04, 0x01, 0x0a, 0x07,
+               0x01, 0x06, 0x0d, 0x00, 0x0b, 0x08, 0x06, 0x0d,
+               0x5c, 0x5a, 0x51, 0x5f, 0x5a, 0x54, 0x5f, 0x52,
+               0x59, 0x57, 0x52, 0x5c, 0x56, 0x59, 0x58, 0x55,
+               0x50, 0x56, 0x5d, 0x51, 0x53, 0x5d, 0x54, 0x5e,
+               0x5e, 0x50, 0x57, 0x5b, 0x55, 0x53, 0x5b, 0x58,
+               0x59, 0x54, 0x5e, 0x53, 0x5f, 0x52, 0x55, 0x5c,
+               0x52, 0x59, 0x58, 0x55, 0x5c, 0x5f, 0x53, 0x5a,
+               0x57, 0x5b, 0x50, 0x5e, 0x54, 0x51, 0x5a, 0x57,
+               0x51, 0x56, 0x5d, 0x50, 0x5b, 0x58, 0x56, 0x5d,
+               0xec, 0xea, 0xe1, 0xef, 0xea, 0xe4, 0xef, 0xe2,
+               0xe9, 0xe7, 0xe2, 0xec, 0xe6, 0xe9, 0xe8, 0xe5,
+               0xe0, 0xe6, 0xed, 0xe1, 0xe3, 0xed, 0xe4, 0xee,
+               0xee, 0xe0, 0xe7, 0xeb, 0xe5, 0xe3, 0xeb, 0xe8,
+               0xe9, 0xe4, 0xee, 0xe3, 0xef, 0xe2, 0xe5, 0xec,
+               0xe2, 0xe9, 0xe8, 0xe5, 0xec, 0xef, 0xe3, 0xea,
+               0xe7, 0xeb, 0xe0, 0xee, 0xe4, 0xe1, 0xea, 0xe7,
+               0xe1, 0xe6, 0xed, 0xe0, 0xeb, 0xe8, 0xe6, 0xed,
+               0x3c, 0x3a, 0x31, 0x3f, 0x3a, 0x34, 0x3f, 0x32,
+               0x39, 0x37, 0x32, 0x3c, 0x36, 0x39, 0x38, 0x35,
+               0x30, 0x36, 0x3d, 0x31, 0x33, 0x3d, 0x34, 0x3e,
+               0x3e, 0x30, 0x37, 0x3b, 0x35, 0x33, 0x3b, 0x38,
+               0x39, 0x34, 0x3e, 0x33, 0x3f, 0x32, 0x35, 0x3c,
+               0x32, 0x39, 0x38, 0x35, 0x3c, 0x3f, 0x33, 0x3a,
+               0x37, 0x3b, 0x30, 0x3e, 0x34, 0x31, 0x3a, 0x37,
+               0x31, 0x36, 0x3d, 0x30, 0x3b, 0x38, 0x36, 0x3d,
+       },{
+               0x4d, 0x41, 0x42, 0x4f, 0x48, 0x4d, 0x44, 0x48,
+               0x46, 0x4a, 0x4f, 0x43, 0x4b, 0x47, 0x41, 0x44,
+               0x4a, 0x4c, 0x49, 0x45, 0x43, 0x46, 0x4e, 0x4b,
+               0x45, 0x40, 0x40, 0x4e, 0x4c, 0x49, 0x47, 0x42,
+               0x47, 0x42, 0x4b, 0x41, 0x44, 0x4e, 0x41, 0x47,
+               0x49, 0x44, 0x4c, 0x4a, 0x4e, 0x48, 0x42, 0x4d,
+               0x40, 0x4f, 0x46, 0x4c, 0x4a, 0x49, 0x4d, 0x40,
+               0x4f, 0x43, 0x43, 0x45, 0x45, 0x46, 0x48, 0x4b,
+               0xdd, 0xd1, 0xd2, 0xdf, 0xd8, 0xdd, 0xd4, 0xd8,
+               0xd6, 0xda, 0xdf, 0xd3, 0xdb, 0xd7, 0xd1, 0xd4,
+               0xda, 0xdc, 0xd9, 0xd5, 0xd3, 0xd6, 0xde, 0xdb,
+               0xd5, 0xd0, 0xd0, 0xde, 0xdc, 0xd9, 0xd7, 0xd2,
+               0xd7, 0xd2, 0xdb, 0xd1, 0xd4, 0xde, 0xd1, 0xd7,
+               0xd9, 0xd4, 0xdc, 0xda, 0xde, 0xd8, 0xd2, 0xdd,
+               0xd0, 0xdf, 0xd6, 0xdc, 0xda, 0xd9, 0xdd, 0xd0,
+               0xdf, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd8, 0xdb,
+               0xbd, 0xb1, 0xb2, 0xbf, 0xb8, 0xbd, 0xb4, 0xb8,
+               0xb6, 0xba, 0xbf, 0xb3, 0xbb, 0xb7, 0xb1, 0xb4,
+               0xba, 0xbc, 0xb9, 0xb5, 0xb3, 0xb6, 0xbe, 0xbb,
+               0xb5, 0xb0, 0xb0, 0xbe, 0xbc, 0xb9, 0xb7, 0xb2,
+               0xb7, 0xb2, 0xbb, 0xb1, 0xb4, 0xbe, 0xb1, 0xb7,
+               0xb9, 0xb4, 0xbc, 0xba, 0xbe, 0xb8, 0xb2, 0xbd,
+               0xb0, 0xbf, 0xb6, 0xbc, 0xba, 0xb9, 0xbd, 0xb0,
+               0xbf, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb8, 0xbb,
+               0x0d, 0x01, 0x02, 0x0f, 0x08, 0x0d, 0x04, 0x08,
+               0x06, 0x0a, 0x0f, 0x03, 0x0b, 0x07, 0x01, 0x04,
+               0x0a, 0x0c, 0x09, 0x05, 0x03, 0x06, 0x0e, 0x0b,
+               0x05, 0x00, 0x00, 0x0e, 0x0c, 0x09, 0x07, 0x02,
+               0x07, 0x02, 0x0b, 0x01, 0x04, 0x0e, 0x01, 0x07,
+               0x09, 0x04, 0x0c, 0x0a, 0x0e, 0x08, 0x02, 0x0d,
+               0x00, 0x0f, 0x06, 0x0c, 0x0a, 0x09, 0x0d, 0x00,
+               0x0f, 0x03, 0x03, 0x05, 0x05, 0x06, 0x08, 0x0b,
+               0x2d, 0x21, 0x22, 0x2f, 0x28, 0x2d, 0x24, 0x28,
+               0x26, 0x2a, 0x2f, 0x23, 0x2b, 0x27, 0x21, 0x24,
+               0x2a, 0x2c, 0x29, 0x25, 0x23, 0x26, 0x2e, 0x2b,
+               0x25, 0x20, 0x20, 0x2e, 0x2c, 0x29, 0x27, 0x22,
+               0x27, 0x22, 0x2b, 0x21, 0x24, 0x2e, 0x21, 0x27,
+               0x29, 0x24, 0x2c, 0x2a, 0x2e, 0x28, 0x22, 0x2d,
+               0x20, 0x2f, 0x26, 0x2c, 0x2a, 0x29, 0x2d, 0x20,
+               0x2f, 0x23, 0x23, 0x25, 0x25, 0x26, 0x28, 0x2b,
+               0xbd, 0xb1, 0xb2, 0xbf, 0xb8, 0xbd, 0xb4, 0xb8,
+               0xb6, 0xba, 0xbf, 0xb3, 0xbb, 0xb7, 0xb1, 0xb4,
+               0xba, 0xbc, 0xb9, 0xb5, 0xb3, 0xb6, 0xbe, 0xbb,
+               0xb5, 0xb0, 0xb0, 0xbe, 0xbc, 0xb9, 0xb7, 0xb2,
+               0xb7, 0xb2, 0xbb, 0xb1, 0xb4, 0xbe, 0xb1, 0xb7,
+               0xb9, 0xb4, 0xbc, 0xba, 0xbe, 0xb8, 0xb2, 0xbd,
+               0xb0, 0xbf, 0xb6, 0xbc, 0xba, 0xb9, 0xbd, 0xb0,
+               0xbf, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb8, 0xbb,
+               0xed, 0xe1, 0xe2, 0xef, 0xe8, 0xed, 0xe4, 0xe8,
+               0xe6, 0xea, 0xef, 0xe3, 0xeb, 0xe7, 0xe1, 0xe4,
+               0xea, 0xec, 0xe9, 0xe5, 0xe3, 0xe6, 0xee, 0xeb,
+               0xe5, 0xe0, 0xe0, 0xee, 0xec, 0xe9, 0xe7, 0xe2,
+               0xe7, 0xe2, 0xeb, 0xe1, 0xe4, 0xee, 0xe1, 0xe7,
+               0xe9, 0xe4, 0xec, 0xea, 0xee, 0xe8, 0xe2, 0xed,
+               0xe0, 0xef, 0xe6, 0xec, 0xea, 0xe9, 0xed, 0xe0,
+               0xef, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe8, 0xeb,
+               0x7d, 0x71, 0x72, 0x7f, 0x78, 0x7d, 0x74, 0x78,
+               0x76, 0x7a, 0x7f, 0x73, 0x7b, 0x77, 0x71, 0x74,
+               0x7a, 0x7c, 0x79, 0x75, 0x73, 0x76, 0x7e, 0x7b,
+               0x75, 0x70, 0x70, 0x7e, 0x7c, 0x79, 0x77, 0x72,
+               0x77, 0x72, 0x7b, 0x71, 0x74, 0x7e, 0x71, 0x77,
+               0x79, 0x74, 0x7c, 0x7a, 0x7e, 0x78, 0x72, 0x7d,
+               0x70, 0x7f, 0x76, 0x7c, 0x7a, 0x79, 0x7d, 0x70,
+               0x7f, 0x73, 0x73, 0x75, 0x75, 0x76, 0x78, 0x7b,
+               0xfd, 0xf1, 0xf2, 0xff, 0xf8, 0xfd, 0xf4, 0xf8,
+               0xf6, 0xfa, 0xff, 0xf3, 0xfb, 0xf7, 0xf1, 0xf4,
+               0xfa, 0xfc, 0xf9, 0xf5, 0xf3, 0xf6, 0xfe, 0xfb,
+               0xf5, 0xf0, 0xf0, 0xfe, 0xfc, 0xf9, 0xf7, 0xf2,
+               0xf7, 0xf2, 0xfb, 0xf1, 0xf4, 0xfe, 0xf1, 0xf7,
+               0xf9, 0xf4, 0xfc, 0xfa, 0xfe, 0xf8, 0xf2, 0xfd,
+               0xf0, 0xff, 0xf6, 0xfc, 0xfa, 0xf9, 0xfd, 0xf0,
+               0xff, 0xf3, 0xf3, 0xf5, 0xf5, 0xf6, 0xf8, 0xfb,
+               0x4d, 0x41, 0x42, 0x4f, 0x48, 0x4d, 0x44, 0x48,
+               0x46, 0x4a, 0x4f, 0x43, 0x4b, 0x47, 0x41, 0x44,
+               0x4a, 0x4c, 0x49, 0x45, 0x43, 0x46, 0x4e, 0x4b,
+               0x45, 0x40, 0x40, 0x4e, 0x4c, 0x49, 0x47, 0x42,
+               0x47, 0x42, 0x4b, 0x41, 0x44, 0x4e, 0x41, 0x47,
+               0x49, 0x44, 0x4c, 0x4a, 0x4e, 0x48, 0x42, 0x4d,
+               0x40, 0x4f, 0x46, 0x4c, 0x4a, 0x49, 0x4d, 0x40,
+               0x4f, 0x43, 0x43, 0x45, 0x45, 0x46, 0x48, 0x4b,
+               0x0d, 0x01, 0x02, 0x0f, 0x08, 0x0d, 0x04, 0x08,
+               0x06, 0x0a, 0x0f, 0x03, 0x0b, 0x07, 0x01, 0x04,
+               0x0a, 0x0c, 0x09, 0x05, 0x03, 0x06, 0x0e, 0x0b,
+               0x05, 0x00, 0x00, 0x0e, 0x0c, 0x09, 0x07, 0x02,
+               0x07, 0x02, 0x0b, 0x01, 0x04, 0x0e, 0x01, 0x07,
+               0x09, 0x04, 0x0c, 0x0a, 0x0e, 0x08, 0x02, 0x0d,
+               0x00, 0x0f, 0x06, 0x0c, 0x0a, 0x09, 0x0d, 0x00,
+               0x0f, 0x03, 0x03, 0x05, 0x05, 0x06, 0x08, 0x0b,
+               0x9d, 0x91, 0x92, 0x9f, 0x98, 0x9d, 0x94, 0x98,
+               0x96, 0x9a, 0x9f, 0x93, 0x9b, 0x97, 0x91, 0x94,
+               0x9a, 0x9c, 0x99, 0x95, 0x93, 0x96, 0x9e, 0x9b,
+               0x95, 0x90, 0x90, 0x9e, 0x9c, 0x99, 0x97, 0x92,
+               0x97, 0x92, 0x9b, 0x91, 0x94, 0x9e, 0x91, 0x97,
+               0x99, 0x94, 0x9c, 0x9a, 0x9e, 0x98, 0x92, 0x9d,
+               0x90, 0x9f, 0x96, 0x9c, 0x9a, 0x99, 0x9d, 0x90,
+               0x9f, 0x93, 0x93, 0x95, 0x95, 0x96, 0x98, 0x9b,
+               0x8d, 0x81, 0x82, 0x8f, 0x88, 0x8d, 0x84, 0x88,
+               0x86, 0x8a, 0x8f, 0x83, 0x8b, 0x87, 0x81, 0x84,
+               0x8a, 0x8c, 0x89, 0x85, 0x83, 0x86, 0x8e, 0x8b,
+               0x85, 0x80, 0x80, 0x8e, 0x8c, 0x89, 0x87, 0x82,
+               0x87, 0x82, 0x8b, 0x81, 0x84, 0x8e, 0x81, 0x87,
+               0x89, 0x84, 0x8c, 0x8a, 0x8e, 0x88, 0x82, 0x8d,
+               0x80, 0x8f, 0x86, 0x8c, 0x8a, 0x89, 0x8d, 0x80,
+               0x8f, 0x83, 0x83, 0x85, 0x85, 0x86, 0x88, 0x8b,
+               0x1d, 0x11, 0x12, 0x1f, 0x18, 0x1d, 0x14, 0x18,
+               0x16, 0x1a, 0x1f, 0x13, 0x1b, 0x17, 0x11, 0x14,
+               0x1a, 0x1c, 0x19, 0x15, 0x13, 0x16, 0x1e, 0x1b,
+               0x15, 0x10, 0x10, 0x1e, 0x1c, 0x19, 0x17, 0x12,
+               0x17, 0x12, 0x1b, 0x11, 0x14, 0x1e, 0x11, 0x17,
+               0x19, 0x14, 0x1c, 0x1a, 0x1e, 0x18, 0x12, 0x1d,
+               0x10, 0x1f, 0x16, 0x1c, 0x1a, 0x19, 0x1d, 0x10,
+               0x1f, 0x13, 0x13, 0x15, 0x15, 0x16, 0x18, 0x1b,
+               0xdd, 0xd1, 0xd2, 0xdf, 0xd8, 0xdd, 0xd4, 0xd8,
+               0xd6, 0xda, 0xdf, 0xd3, 0xdb, 0xd7, 0xd1, 0xd4,
+               0xda, 0xdc, 0xd9, 0xd5, 0xd3, 0xd6, 0xde, 0xdb,
+               0xd5, 0xd0, 0xd0, 0xde, 0xdc, 0xd9, 0xd7, 0xd2,
+               0xd7, 0xd2, 0xdb, 0xd1, 0xd4, 0xde, 0xd1, 0xd7,
+               0xd9, 0xd4, 0xdc, 0xda, 0xde, 0xd8, 0xd2, 0xdd,
+               0xd0, 0xdf, 0xd6, 0xdc, 0xda, 0xd9, 0xdd, 0xd0,
+               0xdf, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd8, 0xdb,
+               0xad, 0xa1, 0xa2, 0xaf, 0xa8, 0xad, 0xa4, 0xa8,
+               0xa6, 0xaa, 0xaf, 0xa3, 0xab, 0xa7, 0xa1, 0xa4,
+               0xaa, 0xac, 0xa9, 0xa5, 0xa3, 0xa6, 0xae, 0xab,
+               0xa5, 0xa0, 0xa0, 0xae, 0xac, 0xa9, 0xa7, 0xa2,
+               0xa7, 0xa2, 0xab, 0xa1, 0xa4, 0xae, 0xa1, 0xa7,
+               0xa9, 0xa4, 0xac, 0xaa, 0xae, 0xa8, 0xa2, 0xad,
+               0xa0, 0xaf, 0xa6, 0xac, 0xaa, 0xa9, 0xad, 0xa0,
+               0xaf, 0xa3, 0xa3, 0xa5, 0xa5, 0xa6, 0xa8, 0xab,
+               0x3d, 0x31, 0x32, 0x3f, 0x38, 0x3d, 0x34, 0x38,
+               0x36, 0x3a, 0x3f, 0x33, 0x3b, 0x37, 0x31, 0x34,
+               0x3a, 0x3c, 0x39, 0x35, 0x33, 0x36, 0x3e, 0x3b,
+               0x35, 0x30, 0x30, 0x3e, 0x3c, 0x39, 0x37, 0x32,
+               0x37, 0x32, 0x3b, 0x31, 0x34, 0x3e, 0x31, 0x37,
+               0x39, 0x34, 0x3c, 0x3a, 0x3e, 0x38, 0x32, 0x3d,
+               0x30, 0x3f, 0x36, 0x3c, 0x3a, 0x39, 0x3d, 0x30,
+               0x3f, 0x33, 0x33, 0x35, 0x35, 0x36, 0x38, 0x3b,
+               0xed, 0xe1, 0xe2, 0xef, 0xe8, 0xed, 0xe4, 0xe8,
+               0xe6, 0xea, 0xef, 0xe3, 0xeb, 0xe7, 0xe1, 0xe4,
+               0xea, 0xec, 0xe9, 0xe5, 0xe3, 0xe6, 0xee, 0xeb,
+               0xe5, 0xe0, 0xe0, 0xee, 0xec, 0xe9, 0xe7, 0xe2,
+               0xe7, 0xe2, 0xeb, 0xe1, 0xe4, 0xee, 0xe1, 0xe7,
+               0xe9, 0xe4, 0xec, 0xea, 0xee, 0xe8, 0xe2, 0xed,
+               0xe0, 0xef, 0xe6, 0xec, 0xea, 0xe9, 0xed, 0xe0,
+               0xef, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe8, 0xeb,
+               0xcd, 0xc1, 0xc2, 0xcf, 0xc8, 0xcd, 0xc4, 0xc8,
+               0xc6, 0xca, 0xcf, 0xc3, 0xcb, 0xc7, 0xc1, 0xc4,
+               0xca, 0xcc, 0xc9, 0xc5, 0xc3, 0xc6, 0xce, 0xcb,
+               0xc5, 0xc0, 0xc0, 0xce, 0xcc, 0xc9, 0xc7, 0xc2,
+               0xc7, 0xc2, 0xcb, 0xc1, 0xc4, 0xce, 0xc1, 0xc7,
+               0xc9, 0xc4, 0xcc, 0xca, 0xce, 0xc8, 0xc2, 0xcd,
+               0xc0, 0xcf, 0xc6, 0xcc, 0xca, 0xc9, 0xcd, 0xc0,
+               0xcf, 0xc3, 0xc3, 0xc5, 0xc5, 0xc6, 0xc8, 0xcb,
+               0x3d, 0x31, 0x32, 0x3f, 0x38, 0x3d, 0x34, 0x38,
+               0x36, 0x3a, 0x3f, 0x33, 0x3b, 0x37, 0x31, 0x34,
+               0x3a, 0x3c, 0x39, 0x35, 0x33, 0x36, 0x3e, 0x3b,
+               0x35, 0x30, 0x30, 0x3e, 0x3c, 0x39, 0x37, 0x32,
+               0x37, 0x32, 0x3b, 0x31, 0x34, 0x3e, 0x31, 0x37,
+               0x39, 0x34, 0x3c, 0x3a, 0x3e, 0x38, 0x32, 0x3d,
+               0x30, 0x3f, 0x36, 0x3c, 0x3a, 0x39, 0x3d, 0x30,
+               0x3f, 0x33, 0x33, 0x35, 0x35, 0x36, 0x38, 0x3b,
+               0x9d, 0x91, 0x92, 0x9f, 0x98, 0x9d, 0x94, 0x98,
+               0x96, 0x9a, 0x9f, 0x93, 0x9b, 0x97, 0x91, 0x94,
+               0x9a, 0x9c, 0x99, 0x95, 0x93, 0x96, 0x9e, 0x9b,
+               0x95, 0x90, 0x90, 0x9e, 0x9c, 0x99, 0x97, 0x92,
+               0x97, 0x92, 0x9b, 0x91, 0x94, 0x9e, 0x91, 0x97,
+               0x99, 0x94, 0x9c, 0x9a, 0x9e, 0x98, 0x92, 0x9d,
+               0x90, 0x9f, 0x96, 0x9c, 0x9a, 0x99, 0x9d, 0x90,
+               0x9f, 0x93, 0x93, 0x95, 0x95, 0x96, 0x98, 0x9b,
+               0x5d, 0x51, 0x52, 0x5f, 0x58, 0x5d, 0x54, 0x58,
+               0x56, 0x5a, 0x5f, 0x53, 0x5b, 0x57, 0x51, 0x54,
+               0x5a, 0x5c, 0x59, 0x55, 0x53, 0x56, 0x5e, 0x5b,
+               0x55, 0x50, 0x50, 0x5e, 0x5c, 0x59, 0x57, 0x52,
+               0x57, 0x52, 0x5b, 0x51, 0x54, 0x5e, 0x51, 0x57,
+               0x59, 0x54, 0x5c, 0x5a, 0x5e, 0x58, 0x52, 0x5d,
+               0x50, 0x5f, 0x56, 0x5c, 0x5a, 0x59, 0x5d, 0x50,
+               0x5f, 0x53, 0x53, 0x55, 0x55, 0x56, 0x58, 0x5b,
+               0x7d, 0x71, 0x72, 0x7f, 0x78, 0x7d, 0x74, 0x78,
+               0x76, 0x7a, 0x7f, 0x73, 0x7b, 0x77, 0x71, 0x74,
+               0x7a, 0x7c, 0x79, 0x75, 0x73, 0x76, 0x7e, 0x7b,
+               0x75, 0x70, 0x70, 0x7e, 0x7c, 0x79, 0x77, 0x72,
+               0x77, 0x72, 0x7b, 0x71, 0x74, 0x7e, 0x71, 0x77,
+               0x79, 0x74, 0x7c, 0x7a, 0x7e, 0x78, 0x72, 0x7d,
+               0x70, 0x7f, 0x76, 0x7c, 0x7a, 0x79, 0x7d, 0x70,
+               0x7f, 0x73, 0x73, 0x75, 0x75, 0x76, 0x78, 0x7b,
+               0xcd, 0xc1, 0xc2, 0xcf, 0xc8, 0xcd, 0xc4, 0xc8,
+               0xc6, 0xca, 0xcf, 0xc3, 0xcb, 0xc7, 0xc1, 0xc4,
+               0xca, 0xcc, 0xc9, 0xc5, 0xc3, 0xc6, 0xce, 0xcb,
+               0xc5, 0xc0, 0xc0, 0xce, 0xcc, 0xc9, 0xc7, 0xc2,
+               0xc7, 0xc2, 0xcb, 0xc1, 0xc4, 0xce, 0xc1, 0xc7,
+               0xc9, 0xc4, 0xcc, 0xca, 0xce, 0xc8, 0xc2, 0xcd,
+               0xc0, 0xcf, 0xc6, 0xcc, 0xca, 0xc9, 0xcd, 0xc0,
+               0xcf, 0xc3, 0xc3, 0xc5, 0xc5, 0xc6, 0xc8, 0xcb,
+               0x5d, 0x51, 0x52, 0x5f, 0x58, 0x5d, 0x54, 0x58,
+               0x56, 0x5a, 0x5f, 0x53, 0x5b, 0x57, 0x51, 0x54,
+               0x5a, 0x5c, 0x59, 0x55, 0x53, 0x56, 0x5e, 0x5b,
+               0x55, 0x50, 0x50, 0x5e, 0x5c, 0x59, 0x57, 0x52,
+               0x57, 0x52, 0x5b, 0x51, 0x54, 0x5e, 0x51, 0x57,
+               0x59, 0x54, 0x5c, 0x5a, 0x5e, 0x58, 0x52, 0x5d,
+               0x50, 0x5f, 0x56, 0x5c, 0x5a, 0x59, 0x5d, 0x50,
+               0x5f, 0x53, 0x53, 0x55, 0x55, 0x56, 0x58, 0x5b,
+               0x2d, 0x21, 0x22, 0x2f, 0x28, 0x2d, 0x24, 0x28,
+               0x26, 0x2a, 0x2f, 0x23, 0x2b, 0x27, 0x21, 0x24,
+               0x2a, 0x2c, 0x29, 0x25, 0x23, 0x26, 0x2e, 0x2b,
+               0x25, 0x20, 0x20, 0x2e, 0x2c, 0x29, 0x27, 0x22,
+               0x27, 0x22, 0x2b, 0x21, 0x24, 0x2e, 0x21, 0x27,
+               0x29, 0x24, 0x2c, 0x2a, 0x2e, 0x28, 0x22, 0x2d,
+               0x20, 0x2f, 0x26, 0x2c, 0x2a, 0x29, 0x2d, 0x20,
+               0x2f, 0x23, 0x23, 0x25, 0x25, 0x26, 0x28, 0x2b,
+               0xad, 0xa1, 0xa2, 0xaf, 0xa8, 0xad, 0xa4, 0xa8,
+               0xa6, 0xaa, 0xaf, 0xa3, 0xab, 0xa7, 0xa1, 0xa4,
+               0xaa, 0xac, 0xa9, 0xa5, 0xa3, 0xa6, 0xae, 0xab,
+               0xa5, 0xa0, 0xa0, 0xae, 0xac, 0xa9, 0xa7, 0xa2,
+               0xa7, 0xa2, 0xab, 0xa1, 0xa4, 0xae, 0xa1, 0xa7,
+               0xa9, 0xa4, 0xac, 0xaa, 0xae, 0xa8, 0xa2, 0xad,
+               0xa0, 0xaf, 0xa6, 0xac, 0xaa, 0xa9, 0xad, 0xa0,
+               0xaf, 0xa3, 0xa3, 0xa5, 0xa5, 0xa6, 0xa8, 0xab,
+               0xfd, 0xf1, 0xf2, 0xff, 0xf8, 0xfd, 0xf4, 0xf8,
+               0xf6, 0xfa, 0xff, 0xf3, 0xfb, 0xf7, 0xf1, 0xf4,
+               0xfa, 0xfc, 0xf9, 0xf5, 0xf3, 0xf6, 0xfe, 0xfb,
+               0xf5, 0xf0, 0xf0, 0xfe, 0xfc, 0xf9, 0xf7, 0xf2,
+               0xf7, 0xf2, 0xfb, 0xf1, 0xf4, 0xfe, 0xf1, 0xf7,
+               0xf9, 0xf4, 0xfc, 0xfa, 0xfe, 0xf8, 0xf2, 0xfd,
+               0xf0, 0xff, 0xf6, 0xfc, 0xfa, 0xf9, 0xfd, 0xf0,
+               0xff, 0xf3, 0xf3, 0xf5, 0xf5, 0xf6, 0xf8, 0xfb,
+               0x6d, 0x61, 0x62, 0x6f, 0x68, 0x6d, 0x64, 0x68,
+               0x66, 0x6a, 0x6f, 0x63, 0x6b, 0x67, 0x61, 0x64,
+               0x6a, 0x6c, 0x69, 0x65, 0x63, 0x66, 0x6e, 0x6b,
+               0x65, 0x60, 0x60, 0x6e, 0x6c, 0x69, 0x67, 0x62,
+               0x67, 0x62, 0x6b, 0x61, 0x64, 0x6e, 0x61, 0x67,
+               0x69, 0x64, 0x6c, 0x6a, 0x6e, 0x68, 0x62, 0x6d,
+               0x60, 0x6f, 0x66, 0x6c, 0x6a, 0x69, 0x6d, 0x60,
+               0x6f, 0x63, 0x63, 0x65, 0x65, 0x66, 0x68, 0x6b,
+               0x8d, 0x81, 0x82, 0x8f, 0x88, 0x8d, 0x84, 0x88,
+               0x86, 0x8a, 0x8f, 0x83, 0x8b, 0x87, 0x81, 0x84,
+               0x8a, 0x8c, 0x89, 0x85, 0x83, 0x86, 0x8e, 0x8b,
+               0x85, 0x80, 0x80, 0x8e, 0x8c, 0x89, 0x87, 0x82,
+               0x87, 0x82, 0x8b, 0x81, 0x84, 0x8e, 0x81, 0x87,
+               0x89, 0x84, 0x8c, 0x8a, 0x8e, 0x88, 0x82, 0x8d,
+               0x80, 0x8f, 0x86, 0x8c, 0x8a, 0x89, 0x8d, 0x80,
+               0x8f, 0x83, 0x83, 0x85, 0x85, 0x86, 0x88, 0x8b,
+               0x1d, 0x11, 0x12, 0x1f, 0x18, 0x1d, 0x14, 0x18,
+               0x16, 0x1a, 0x1f, 0x13, 0x1b, 0x17, 0x11, 0x14,
+               0x1a, 0x1c, 0x19, 0x15, 0x13, 0x16, 0x1e, 0x1b,
+               0x15, 0x10, 0x10, 0x1e, 0x1c, 0x19, 0x17, 0x12,
+               0x17, 0x12, 0x1b, 0x11, 0x14, 0x1e, 0x11, 0x17,
+               0x19, 0x14, 0x1c, 0x1a, 0x1e, 0x18, 0x12, 0x1d,
+               0x10, 0x1f, 0x16, 0x1c, 0x1a, 0x19, 0x1d, 0x10,
+               0x1f, 0x13, 0x13, 0x15, 0x15, 0x16, 0x18, 0x1b,
+               0x6d, 0x61, 0x62, 0x6f, 0x68, 0x6d, 0x64, 0x68,
+               0x66, 0x6a, 0x6f, 0x63, 0x6b, 0x67, 0x61, 0x64,
+               0x6a, 0x6c, 0x69, 0x65, 0x63, 0x66, 0x6e, 0x6b,
+               0x65, 0x60, 0x60, 0x6e, 0x6c, 0x69, 0x67, 0x62,
+               0x67, 0x62, 0x6b, 0x61, 0x64, 0x6e, 0x61, 0x67,
+               0x69, 0x64, 0x6c, 0x6a, 0x6e, 0x68, 0x62, 0x6d,
+               0x60, 0x6f, 0x66, 0x6c, 0x6a, 0x69, 0x6d, 0x60,
+               0x6f, 0x63, 0x63, 0x65, 0x65, 0x66, 0x68, 0x6b,
+               0x1d, 0x11, 0x12, 0x1f, 0x18, 0x1d, 0x14, 0x18,
+               0x16, 0x1a, 0x1f, 0x13, 0x1b, 0x17, 0x11, 0x14,
+               0x1a, 0x1c, 0x19, 0x15, 0x13, 0x16, 0x1e, 0x1b,
+               0x15, 0x10, 0x10, 0x1e, 0x1c, 0x19, 0x17, 0x12,
+               0x17, 0x12, 0x1b, 0x11, 0x14, 0x1e, 0x11, 0x17,
+               0x19, 0x14, 0x1c, 0x1a, 0x1e, 0x18, 0x12, 0x1d,
+               0x10, 0x1f, 0x16, 0x1c, 0x1a, 0x19, 0x1d, 0x10,
+               0x1f, 0x13, 0x13, 0x15, 0x15, 0x16, 0x18, 0x1b,
+               0x6d, 0x61, 0x62, 0x6f, 0x68, 0x6d, 0x64, 0x68,
+               0x66, 0x6a, 0x6f, 0x63, 0x6b, 0x67, 0x61, 0x64,
+               0x6a, 0x6c, 0x69, 0x65, 0x63, 0x66, 0x6e, 0x6b,
+               0x65, 0x60, 0x60, 0x6e, 0x6c, 0x69, 0x67, 0x62,
+               0x67, 0x62, 0x6b, 0x61, 0x64, 0x6e, 0x61, 0x67,
+               0x69, 0x64, 0x6c, 0x6a, 0x6e, 0x68, 0x62, 0x6d,
+               0x60, 0x6f, 0x66, 0x6c, 0x6a, 0x69, 0x6d, 0x60,
+               0x6f, 0x63, 0x63, 0x65, 0x65, 0x66, 0x68, 0x6b,
+               0x4d, 0x41, 0x42, 0x4f, 0x48, 0x4d, 0x44, 0x48,
+               0x46, 0x4a, 0x4f, 0x43, 0x4b, 0x47, 0x41, 0x44,
+               0x4a, 0x4c, 0x49, 0x45, 0x43, 0x46, 0x4e, 0x4b,
+               0x45, 0x40, 0x40, 0x4e, 0x4c, 0x49, 0x47, 0x42,
+               0x47, 0x42, 0x4b, 0x41, 0x44, 0x4e, 0x41, 0x47,
+               0x49, 0x44, 0x4c, 0x4a, 0x4e, 0x48, 0x42, 0x4d,
+               0x40, 0x4f, 0x46, 0x4c, 0x4a, 0x49, 0x4d, 0x40,
+               0x4f, 0x43, 0x43, 0x45, 0x45, 0x46, 0x48, 0x4b,
+               0xbd, 0xb1, 0xb2, 0xbf, 0xb8, 0xbd, 0xb4, 0xb8,
+               0xb6, 0xba, 0xbf, 0xb3, 0xbb, 0xb7, 0xb1, 0xb4,
+               0xba, 0xbc, 0xb9, 0xb5, 0xb3, 0xb6, 0xbe, 0xbb,
+               0xb5, 0xb0, 0xb0, 0xbe, 0xbc, 0xb9, 0xb7, 0xb2,
+               0xb7, 0xb2, 0xbb, 0xb1, 0xb4, 0xbe, 0xb1, 0xb7,
+               0xb9, 0xb4, 0xbc, 0xba, 0xbe, 0xb8, 0xb2, 0xbd,
+               0xb0, 0xbf, 0xb6, 0xbc, 0xba, 0xb9, 0xbd, 0xb0,
+               0xbf, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb8, 0xbb,
+               0xbd, 0xb1, 0xb2, 0xbf, 0xb8, 0xbd, 0xb4, 0xb8,
+               0xb6, 0xba, 0xbf, 0xb3, 0xbb, 0xb7, 0xb1, 0xb4,
+               0xba, 0xbc, 0xb9, 0xb5, 0xb3, 0xb6, 0xbe, 0xbb,
+               0xb5, 0xb0, 0xb0, 0xbe, 0xbc, 0xb9, 0xb7, 0xb2,
+               0xb7, 0xb2, 0xbb, 0xb1, 0xb4, 0xbe, 0xb1, 0xb7,
+               0xb9, 0xb4, 0xbc, 0xba, 0xbe, 0xb8, 0xb2, 0xbd,
+               0xb0, 0xbf, 0xb6, 0xbc, 0xba, 0xb9, 0xbd, 0xb0,
+               0xbf, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb8, 0xbb,
+               0xdd, 0xd1, 0xd2, 0xdf, 0xd8, 0xdd, 0xd4, 0xd8,
+               0xd6, 0xda, 0xdf, 0xd3, 0xdb, 0xd7, 0xd1, 0xd4,
+               0xda, 0xdc, 0xd9, 0xd5, 0xd3, 0xd6, 0xde, 0xdb,
+               0xd5, 0xd0, 0xd0, 0xde, 0xdc, 0xd9, 0xd7, 0xd2,
+               0xd7, 0xd2, 0xdb, 0xd1, 0xd4, 0xde, 0xd1, 0xd7,
+               0xd9, 0xd4, 0xdc, 0xda, 0xde, 0xd8, 0xd2, 0xdd,
+               0xd0, 0xdf, 0xd6, 0xdc, 0xda, 0xd9, 0xdd, 0xd0,
+               0xdf, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd8, 0xdb,
+               0xdd, 0xd1, 0xd2, 0xdf, 0xd8, 0xdd, 0xd4, 0xd8,
+               0xd6, 0xda, 0xdf, 0xd3, 0xdb, 0xd7, 0xd1, 0xd4,
+               0xda, 0xdc, 0xd9, 0xd5, 0xd3, 0xd6, 0xde, 0xdb,
+               0xd5, 0xd0, 0xd0, 0xde, 0xdc, 0xd9, 0xd7, 0xd2,
+               0xd7, 0xd2, 0xdb, 0xd1, 0xd4, 0xde, 0xd1, 0xd7,
+               0xd9, 0xd4, 0xdc, 0xda, 0xde, 0xd8, 0xd2, 0xdd,
+               0xd0, 0xdf, 0xd6, 0xdc, 0xda, 0xd9, 0xdd, 0xd0,
+               0xdf, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd8, 0xdb,
+               0x8d, 0x81, 0x82, 0x8f, 0x88, 0x8d, 0x84, 0x88,
+               0x86, 0x8a, 0x8f, 0x83, 0x8b, 0x87, 0x81, 0x84,
+               0x8a, 0x8c, 0x89, 0x85, 0x83, 0x86, 0x8e, 0x8b,
+               0x85, 0x80, 0x80, 0x8e, 0x8c, 0x89, 0x87, 0x82,
+               0x87, 0x82, 0x8b, 0x81, 0x84, 0x8e, 0x81, 0x87,
+               0x89, 0x84, 0x8c, 0x8a, 0x8e, 0x88, 0x82, 0x8d,
+               0x80, 0x8f, 0x86, 0x8c, 0x8a, 0x89, 0x8d, 0x80,
+               0x8f, 0x83, 0x83, 0x85, 0x85, 0x86, 0x88, 0x8b,
+               0xcd, 0xc1, 0xc2, 0xcf, 0xc8, 0xcd, 0xc4, 0xc8,
+               0xc6, 0xca, 0xcf, 0xc3, 0xcb, 0xc7, 0xc1, 0xc4,
+               0xca, 0xcc, 0xc9, 0xc5, 0xc3, 0xc6, 0xce, 0xcb,
+               0xc5, 0xc0, 0xc0, 0xce, 0xcc, 0xc9, 0xc7, 0xc2,
+               0xc7, 0xc2, 0xcb, 0xc1, 0xc4, 0xce, 0xc1, 0xc7,
+               0xc9, 0xc4, 0xcc, 0xca, 0xce, 0xc8, 0xc2, 0xcd,
+               0xc0, 0xcf, 0xc6, 0xcc, 0xca, 0xc9, 0xcd, 0xc0,
+               0xcf, 0xc3, 0xc3, 0xc5, 0xc5, 0xc6, 0xc8, 0xcb,
+               0x1d, 0x11, 0x12, 0x1f, 0x18, 0x1d, 0x14, 0x18,
+               0x16, 0x1a, 0x1f, 0x13, 0x1b, 0x17, 0x11, 0x14,
+               0x1a, 0x1c, 0x19, 0x15, 0x13, 0x16, 0x1e, 0x1b,
+               0x15, 0x10, 0x10, 0x1e, 0x1c, 0x19, 0x17, 0x12,
+               0x17, 0x12, 0x1b, 0x11, 0x14, 0x1e, 0x11, 0x17,
+               0x19, 0x14, 0x1c, 0x1a, 0x1e, 0x18, 0x12, 0x1d,
+               0x10, 0x1f, 0x16, 0x1c, 0x1a, 0x19, 0x1d, 0x10,
+               0x1f, 0x13, 0x13, 0x15, 0x15, 0x16, 0x18, 0x1b,
+               0x3d, 0x31, 0x32, 0x3f, 0x38, 0x3d, 0x34, 0x38,
+               0x36, 0x3a, 0x3f, 0x33, 0x3b, 0x37, 0x31, 0x34,
+               0x3a, 0x3c, 0x39, 0x35, 0x33, 0x36, 0x3e, 0x3b,
+               0x35, 0x30, 0x30, 0x3e, 0x3c, 0x39, 0x37, 0x32,
+               0x37, 0x32, 0x3b, 0x31, 0x34, 0x3e, 0x31, 0x37,
+               0x39, 0x34, 0x3c, 0x3a, 0x3e, 0x38, 0x32, 0x3d,
+               0x30, 0x3f, 0x36, 0x3c, 0x3a, 0x39, 0x3d, 0x30,
+               0x3f, 0x33, 0x33, 0x35, 0x35, 0x36, 0x38, 0x3b,
+               0x4d, 0x41, 0x42, 0x4f, 0x48, 0x4d, 0x44, 0x48,
+               0x46, 0x4a, 0x4f, 0x43, 0x4b, 0x47, 0x41, 0x44,
+               0x4a, 0x4c, 0x49, 0x45, 0x43, 0x46, 0x4e, 0x4b,
+               0x45, 0x40, 0x40, 0x4e, 0x4c, 0x49, 0x47, 0x42,
+               0x47, 0x42, 0x4b, 0x41, 0x44, 0x4e, 0x41, 0x47,
+               0x49, 0x44, 0x4c, 0x4a, 0x4e, 0x48, 0x42, 0x4d,
+               0x40, 0x4f, 0x46, 0x4c, 0x4a, 0x49, 0x4d, 0x40,
+               0x4f, 0x43, 0x43, 0x45, 0x45, 0x46, 0x48, 0x4b,
+               0x7d, 0x71, 0x72, 0x7f, 0x78, 0x7d, 0x74, 0x78,
+               0x76, 0x7a, 0x7f, 0x73, 0x7b, 0x77, 0x71, 0x74,
+               0x7a, 0x7c, 0x79, 0x75, 0x73, 0x76, 0x7e, 0x7b,
+               0x75, 0x70, 0x70, 0x7e, 0x7c, 0x79, 0x77, 0x72,
+               0x77, 0x72, 0x7b, 0x71, 0x74, 0x7e, 0x71, 0x77,
+               0x79, 0x74, 0x7c, 0x7a, 0x7e, 0x78, 0x72, 0x7d,
+               0x70, 0x7f, 0x76, 0x7c, 0x7a, 0x79, 0x7d, 0x70,
+               0x7f, 0x73, 0x73, 0x75, 0x75, 0x76, 0x78, 0x7b,
+               0xad, 0xa1, 0xa2, 0xaf, 0xa8, 0xad, 0xa4, 0xa8,
+               0xa6, 0xaa, 0xaf, 0xa3, 0xab, 0xa7, 0xa1, 0xa4,
+               0xaa, 0xac, 0xa9, 0xa5, 0xa3, 0xa6, 0xae, 0xab,
+               0xa5, 0xa0, 0xa0, 0xae, 0xac, 0xa9, 0xa7, 0xa2,
+               0xa7, 0xa2, 0xab, 0xa1, 0xa4, 0xae, 0xa1, 0xa7,
+               0xa9, 0xa4, 0xac, 0xaa, 0xae, 0xa8, 0xa2, 0xad,
+               0xa0, 0xaf, 0xa6, 0xac, 0xaa, 0xa9, 0xad, 0xa0,
+               0xaf, 0xa3, 0xa3, 0xa5, 0xa5, 0xa6, 0xa8, 0xab,
+               0xed, 0xe1, 0xe2, 0xef, 0xe8, 0xed, 0xe4, 0xe8,
+               0xe6, 0xea, 0xef, 0xe3, 0xeb, 0xe7, 0xe1, 0xe4,
+               0xea, 0xec, 0xe9, 0xe5, 0xe3, 0xe6, 0xee, 0xeb,
+               0xe5, 0xe0, 0xe0, 0xee, 0xec, 0xe9, 0xe7, 0xe2,
+               0xe7, 0xe2, 0xeb, 0xe1, 0xe4, 0xee, 0xe1, 0xe7,
+               0xe9, 0xe4, 0xec, 0xea, 0xee, 0xe8, 0xe2, 0xed,
+               0xe0, 0xef, 0xe6, 0xec, 0xea, 0xe9, 0xed, 0xe0,
+               0xef, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe8, 0xeb,
+               0x7d, 0x71, 0x72, 0x7f, 0x78, 0x7d, 0x74, 0x78,
+               0x76, 0x7a, 0x7f, 0x73, 0x7b, 0x77, 0x71, 0x74,
+               0x7a, 0x7c, 0x79, 0x75, 0x73, 0x76, 0x7e, 0x7b,
+               0x75, 0x70, 0x70, 0x7e, 0x7c, 0x79, 0x77, 0x72,
+               0x77, 0x72, 0x7b, 0x71, 0x74, 0x7e, 0x71, 0x77,
+               0x79, 0x74, 0x7c, 0x7a, 0x7e, 0x78, 0x72, 0x7d,
+               0x70, 0x7f, 0x76, 0x7c, 0x7a, 0x79, 0x7d, 0x70,
+               0x7f, 0x73, 0x73, 0x75, 0x75, 0x76, 0x78, 0x7b,
+               0xad, 0xa1, 0xa2, 0xaf, 0xa8, 0xad, 0xa4, 0xa8,
+               0xa6, 0xaa, 0xaf, 0xa3, 0xab, 0xa7, 0xa1, 0xa4,
+               0xaa, 0xac, 0xa9, 0xa5, 0xa3, 0xa6, 0xae, 0xab,
+               0xa5, 0xa0, 0xa0, 0xae, 0xac, 0xa9, 0xa7, 0xa2,
+               0xa7, 0xa2, 0xab, 0xa1, 0xa4, 0xae, 0xa1, 0xa7,
+               0xa9, 0xa4, 0xac, 0xaa, 0xae, 0xa8, 0xa2, 0xad,
+               0xa0, 0xaf, 0xa6, 0xac, 0xaa, 0xa9, 0xad, 0xa0,
+               0xaf, 0xa3, 0xa3, 0xa5, 0xa5, 0xa6, 0xa8, 0xab,
+               0x9d, 0x91, 0x92, 0x9f, 0x98, 0x9d, 0x94, 0x98,
+               0x96, 0x9a, 0x9f, 0x93, 0x9b, 0x97, 0x91, 0x94,
+               0x9a, 0x9c, 0x99, 0x95, 0x93, 0x96, 0x9e, 0x9b,
+               0x95, 0x90, 0x90, 0x9e, 0x9c, 0x99, 0x97, 0x92,
+               0x97, 0x92, 0x9b, 0x91, 0x94, 0x9e, 0x91, 0x97,
+               0x99, 0x94, 0x9c, 0x9a, 0x9e, 0x98, 0x92, 0x9d,
+               0x90, 0x9f, 0x96, 0x9c, 0x9a, 0x99, 0x9d, 0x90,
+               0x9f, 0x93, 0x93, 0x95, 0x95, 0x96, 0x98, 0x9b,
+               0xfd, 0xf1, 0xf2, 0xff, 0xf8, 0xfd, 0xf4, 0xf8,
+               0xf6, 0xfa, 0xff, 0xf3, 0xfb, 0xf7, 0xf1, 0xf4,
+               0xfa, 0xfc, 0xf9, 0xf5, 0xf3, 0xf6, 0xfe, 0xfb,
+               0xf5, 0xf0, 0xf0, 0xfe, 0xfc, 0xf9, 0xf7, 0xf2,
+               0xf7, 0xf2, 0xfb, 0xf1, 0xf4, 0xfe, 0xf1, 0xf7,
+               0xf9, 0xf4, 0xfc, 0xfa, 0xfe, 0xf8, 0xf2, 0xfd,
+               0xf0, 0xff, 0xf6, 0xfc, 0xfa, 0xf9, 0xfd, 0xf0,
+               0xff, 0xf3, 0xf3, 0xf5, 0xf5, 0xf6, 0xf8, 0xfb,
+               0x5d, 0x51, 0x52, 0x5f, 0x58, 0x5d, 0x54, 0x58,
+               0x56, 0x5a, 0x5f, 0x53, 0x5b, 0x57, 0x51, 0x54,
+               0x5a, 0x5c, 0x59, 0x55, 0x53, 0x56, 0x5e, 0x5b,
+               0x55, 0x50, 0x50, 0x5e, 0x5c, 0x59, 0x57, 0x52,
+               0x57, 0x52, 0x5b, 0x51, 0x54, 0x5e, 0x51, 0x57,
+               0x59, 0x54, 0x5c, 0x5a, 0x5e, 0x58, 0x52, 0x5d,
+               0x50, 0x5f, 0x56, 0x5c, 0x5a, 0x59, 0x5d, 0x50,
+               0x5f, 0x53, 0x53, 0x55, 0x55, 0x56, 0x58, 0x5b,
+               0x6d, 0x61, 0x62, 0x6f, 0x68, 0x6d, 0x64, 0x68,
+               0x66, 0x6a, 0x6f, 0x63, 0x6b, 0x67, 0x61, 0x64,
+               0x6a, 0x6c, 0x69, 0x65, 0x63, 0x66, 0x6e, 0x6b,
+               0x65, 0x60, 0x60, 0x6e, 0x6c, 0x69, 0x67, 0x62,
+               0x67, 0x62, 0x6b, 0x61, 0x64, 0x6e, 0x61, 0x67,
+               0x69, 0x64, 0x6c, 0x6a, 0x6e, 0x68, 0x62, 0x6d,
+               0x60, 0x6f, 0x66, 0x6c, 0x6a, 0x69, 0x6d, 0x60,
+               0x6f, 0x63, 0x63, 0x65, 0x65, 0x66, 0x68, 0x6b,
+               0x0d, 0x01, 0x02, 0x0f, 0x08, 0x0d, 0x04, 0x08,
+               0x06, 0x0a, 0x0f, 0x03, 0x0b, 0x07, 0x01, 0x04,
+               0x0a, 0x0c, 0x09, 0x05, 0x03, 0x06, 0x0e, 0x0b,
+               0x05, 0x00, 0x00, 0x0e, 0x0c, 0x09, 0x07, 0x02,
+               0x07, 0x02, 0x0b, 0x01, 0x04, 0x0e, 0x01, 0x07,
+               0x09, 0x04, 0x0c, 0x0a, 0x0e, 0x08, 0x02, 0x0d,
+               0x00, 0x0f, 0x06, 0x0c, 0x0a, 0x09, 0x0d, 0x00,
+               0x0f, 0x03, 0x03, 0x05, 0x05, 0x06, 0x08, 0x0b,
+               0x8d, 0x81, 0x82, 0x8f, 0x88, 0x8d, 0x84, 0x88,
+               0x86, 0x8a, 0x8f, 0x83, 0x8b, 0x87, 0x81, 0x84,
+               0x8a, 0x8c, 0x89, 0x85, 0x83, 0x86, 0x8e, 0x8b,
+               0x85, 0x80, 0x80, 0x8e, 0x8c, 0x89, 0x87, 0x82,
+               0x87, 0x82, 0x8b, 0x81, 0x84, 0x8e, 0x81, 0x87,
+               0x89, 0x84, 0x8c, 0x8a, 0x8e, 0x88, 0x82, 0x8d,
+               0x80, 0x8f, 0x86, 0x8c, 0x8a, 0x89, 0x8d, 0x80,
+               0x8f, 0x83, 0x83, 0x85, 0x85, 0x86, 0x88, 0x8b,
+               0xfd, 0xf1, 0xf2, 0xff, 0xf8, 0xfd, 0xf4, 0xf8,
+               0xf6, 0xfa, 0xff, 0xf3, 0xfb, 0xf7, 0xf1, 0xf4,
+               0xfa, 0xfc, 0xf9, 0xf5, 0xf3, 0xf6, 0xfe, 0xfb,
+               0xf5, 0xf0, 0xf0, 0xfe, 0xfc, 0xf9, 0xf7, 0xf2,
+               0xf7, 0xf2, 0xfb, 0xf1, 0xf4, 0xfe, 0xf1, 0xf7,
+               0xf9, 0xf4, 0xfc, 0xfa, 0xfe, 0xf8, 0xf2, 0xfd,
+               0xf0, 0xff, 0xf6, 0xfc, 0xfa, 0xf9, 0xfd, 0xf0,
+               0xff, 0xf3, 0xf3, 0xf5, 0xf5, 0xf6, 0xf8, 0xfb,
+               0x0d, 0x01, 0x02, 0x0f, 0x08, 0x0d, 0x04, 0x08,
+               0x06, 0x0a, 0x0f, 0x03, 0x0b, 0x07, 0x01, 0x04,
+               0x0a, 0x0c, 0x09, 0x05, 0x03, 0x06, 0x0e, 0x0b,
+               0x05, 0x00, 0x00, 0x0e, 0x0c, 0x09, 0x07, 0x02,
+               0x07, 0x02, 0x0b, 0x01, 0x04, 0x0e, 0x01, 0x07,
+               0x09, 0x04, 0x0c, 0x0a, 0x0e, 0x08, 0x02, 0x0d,
+               0x00, 0x0f, 0x06, 0x0c, 0x0a, 0x09, 0x0d, 0x00,
+               0x0f, 0x03, 0x03, 0x05, 0x05, 0x06, 0x08, 0x0b,
+               0xed, 0xe1, 0xe2, 0xef, 0xe8, 0xed, 0xe4, 0xe8,
+               0xe6, 0xea, 0xef, 0xe3, 0xeb, 0xe7, 0xe1, 0xe4,
+               0xea, 0xec, 0xe9, 0xe5, 0xe3, 0xe6, 0xee, 0xeb,
+               0xe5, 0xe0, 0xe0, 0xee, 0xec, 0xe9, 0xe7, 0xe2,
+               0xe7, 0xe2, 0xeb, 0xe1, 0xe4, 0xee, 0xe1, 0xe7,
+               0xe9, 0xe4, 0xec, 0xea, 0xee, 0xe8, 0xe2, 0xed,
+               0xe0, 0xef, 0xe6, 0xec, 0xea, 0xe9, 0xed, 0xe0,
+               0xef, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe8, 0xeb,
+               0x5d, 0x51, 0x52, 0x5f, 0x58, 0x5d, 0x54, 0x58,
+               0x56, 0x5a, 0x5f, 0x53, 0x5b, 0x57, 0x51, 0x54,
+               0x5a, 0x5c, 0x59, 0x55, 0x53, 0x56, 0x5e, 0x5b,
+               0x55, 0x50, 0x50, 0x5e, 0x5c, 0x59, 0x57, 0x52,
+               0x57, 0x52, 0x5b, 0x51, 0x54, 0x5e, 0x51, 0x57,
+               0x59, 0x54, 0x5c, 0x5a, 0x5e, 0x58, 0x52, 0x5d,
+               0x50, 0x5f, 0x56, 0x5c, 0x5a, 0x59, 0x5d, 0x50,
+               0x5f, 0x53, 0x53, 0x55, 0x55, 0x56, 0x58, 0x5b,
+               0x2d, 0x21, 0x22, 0x2f, 0x28, 0x2d, 0x24, 0x28,
+               0x26, 0x2a, 0x2f, 0x23, 0x2b, 0x27, 0x21, 0x24,
+               0x2a, 0x2c, 0x29, 0x25, 0x23, 0x26, 0x2e, 0x2b,
+               0x25, 0x20, 0x20, 0x2e, 0x2c, 0x29, 0x27, 0x22,
+               0x27, 0x22, 0x2b, 0x21, 0x24, 0x2e, 0x21, 0x27,
+               0x29, 0x24, 0x2c, 0x2a, 0x2e, 0x28, 0x22, 0x2d,
+               0x20, 0x2f, 0x26, 0x2c, 0x2a, 0x29, 0x2d, 0x20,
+               0x2f, 0x23, 0x23, 0x25, 0x25, 0x26, 0x28, 0x2b,
+               0x9d, 0x91, 0x92, 0x9f, 0x98, 0x9d, 0x94, 0x98,
+               0x96, 0x9a, 0x9f, 0x93, 0x9b, 0x97, 0x91, 0x94,
+               0x9a, 0x9c, 0x99, 0x95, 0x93, 0x96, 0x9e, 0x9b,
+               0x95, 0x90, 0x90, 0x9e, 0x9c, 0x99, 0x97, 0x92,
+               0x97, 0x92, 0x9b, 0x91, 0x94, 0x9e, 0x91, 0x97,
+               0x99, 0x94, 0x9c, 0x9a, 0x9e, 0x98, 0x92, 0x9d,
+               0x90, 0x9f, 0x96, 0x9c, 0x9a, 0x99, 0x9d, 0x90,
+               0x9f, 0x93, 0x93, 0x95, 0x95, 0x96, 0x98, 0x9b,
+               0x3d, 0x31, 0x32, 0x3f, 0x38, 0x3d, 0x34, 0x38,
+               0x36, 0x3a, 0x3f, 0x33, 0x3b, 0x37, 0x31, 0x34,
+               0x3a, 0x3c, 0x39, 0x35, 0x33, 0x36, 0x3e, 0x3b,
+               0x35, 0x30, 0x30, 0x3e, 0x3c, 0x39, 0x37, 0x32,
+               0x37, 0x32, 0x3b, 0x31, 0x34, 0x3e, 0x31, 0x37,
+               0x39, 0x34, 0x3c, 0x3a, 0x3e, 0x38, 0x32, 0x3d,
+               0x30, 0x3f, 0x36, 0x3c, 0x3a, 0x39, 0x3d, 0x30,
+               0x3f, 0x33, 0x33, 0x35, 0x35, 0x36, 0x38, 0x3b,
+               0x2d, 0x21, 0x22, 0x2f, 0x28, 0x2d, 0x24, 0x28,
+               0x26, 0x2a, 0x2f, 0x23, 0x2b, 0x27, 0x21, 0x24,
+               0x2a, 0x2c, 0x29, 0x25, 0x23, 0x26, 0x2e, 0x2b,
+               0x25, 0x20, 0x20, 0x2e, 0x2c, 0x29, 0x27, 0x22,
+               0x27, 0x22, 0x2b, 0x21, 0x24, 0x2e, 0x21, 0x27,
+               0x29, 0x24, 0x2c, 0x2a, 0x2e, 0x28, 0x22, 0x2d,
+               0x20, 0x2f, 0x26, 0x2c, 0x2a, 0x29, 0x2d, 0x20,
+               0x2f, 0x23, 0x23, 0x25, 0x25, 0x26, 0x28, 0x2b,
+               0xcd, 0xc1, 0xc2, 0xcf, 0xc8, 0xcd, 0xc4, 0xc8,
+               0xc6, 0xca, 0xcf, 0xc3, 0xcb, 0xc7, 0xc1, 0xc4,
+               0xca, 0xcc, 0xc9, 0xc5, 0xc3, 0xc6, 0xce, 0xcb,
+               0xc5, 0xc0, 0xc0, 0xce, 0xcc, 0xc9, 0xc7, 0xc2,
+               0xc7, 0xc2, 0xcb, 0xc1, 0xc4, 0xce, 0xc1, 0xc7,
+               0xc9, 0xc4, 0xcc, 0xca, 0xce, 0xc8, 0xc2, 0xcd,
+               0xc0, 0xcf, 0xc6, 0xcc, 0xca, 0xc9, 0xcd, 0xc0,
+               0xcf, 0xc3, 0xc3, 0xc5, 0xc5, 0xc6, 0xc8, 0xcb,
+       },
+};
+
+static const uint8_t key_perm[56] = {
+       57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
+       10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
+       63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
+       14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
+};
+
+static const uint8_t key_shifts[16] = {
+       1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+static const uint8_t comp_perm[48] = {
+       14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
+       23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
+       41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
+       44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
+};
+
+static const uint8_t pbox[32] = {
+       16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
+        2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
+};
+
+static int
+ascii_to_bin(char ch)
+{
+       if (ch > 'z')
+               return 0;
+       if (ch >= 'a')
+               return (ch - 'a' + 38);
+       if (ch > 'Z')
+               return 0;
+       if (ch >= 'A')
+               return (ch - 'A' + 12);
+       if (ch > '9')
+               return 0;
+       if (ch >= '.')
+               return (ch - '.');
+       return 0;
+}
+
+
+
+struct des_ctx {
+       uint32_t saltbits; /* referenced 5 times */
+       uint8_t un_pbox[32]; /* 2 times */
+       uint8_t inv_comp_perm[56]; /* 3 times */
+       uint8_t inv_key_perm[64]; /* 3 times */
+       uint32_t en_keysl[16], en_keysr[16]; /* 2 times each */
+       uint32_t fp_maskl[8][256], fp_maskr[8][256]; /* 9 times each */
+       uint32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; /* 9 times */
+       uint32_t comp_maskl[8][128], comp_maskr[8][128]; /* 9 times each */
+       uint32_t psbox[4][256]; /* 5 times */
+};
+#define D (*ctx)
+#define saltbits        (D.saltbits       )
+#define old_salt        (D.old_salt       )
+#define old_rawkey0     (D.old_rawkey0    )
+#define old_rawkey1     (D.old_rawkey1    )
+#define un_pbox         (D.un_pbox        )
+#define inv_comp_perm   (D.inv_comp_perm  )
+#define inv_key_perm    (D.inv_key_perm   )
+#define en_keysl        (D.en_keysl       )
+#define en_keysr        (D.en_keysr       )
+#define de_keysl        (D.de_keysl       )
+#define de_keysr        (D.de_keysr       )
+#define ip_maskl        (D.ip_maskl       )
+#define ip_maskr        (D.ip_maskr       )
+#define fp_maskl        (D.fp_maskl       )
+#define fp_maskr        (D.fp_maskr       )
+#define key_perm_maskl  (D.key_perm_maskl )
+#define key_perm_maskr  (D.key_perm_maskr )
+#define comp_maskl      (D.comp_maskl     )
+#define comp_maskr      (D.comp_maskr     )
+#define psbox           (D.psbox          )
+
+static struct des_ctx *des_init(struct des_ctx *ctx)
+{
+       int i, j, b, k, inbit, obit;
+       uint32_t p;
+
+       saltbits = 0;
+
+       /* Initialise the inverted key permutation. */
+       for (i = 0; i < 64; i++) {
+               inv_key_perm[i] = 255;
+       }
+
+       /*
+        * Invert the key permutation and initialise the inverted key
+        * compression permutation.
+        */
+       for (i = 0; i < 56; i++) {
+               inv_key_perm[key_perm[i] - 1] = (uint8_t)i;
+               inv_comp_perm[i] = 255;
+       }
+
+       /* Invert the key compression permutation. */
+       for (i = 0; i < 48; i++) {
+               inv_comp_perm[comp_perm[i] - 1] = (uint8_t)i;
+       }
+
+       /*
+        * Set up the OR-mask arrays for the initial and final permutations,
+        * and for the key initial and compression permutations.
+        */
+       for (k = 0; k < 8; k++) {
+               uint32_t il, ir;
+               uint32_t fl, fr;
+               for (i = 0; i < 256; i++) {
+                       fl = 0;
+                       fr = 0;
+                       for (j = 0; j < 8; j++) {
+                               inbit = 8 * k + j;
+                               if (i & (0x80>>j)) {
+                                       obit = final_perm[inbit];
+                                       if (obit < 32)
+                                               fl |= 0x80000000UL >> obit;
+                                       else
+                                               fr |= 0x80000000UL >> obit-32;
+                               }
+                       }
+                       fp_maskl[k][i] = fl;
+                       fp_maskr[k][i] = fr;
+               }
+               for (i = 0; i < 128; i++) {
+                       il = 0;
+                       ir = 0;
+                       for (j = 0; j < 7; j++) {
+                               inbit = 8 * k + j;
+                               if (i & (0x80 >> j + 1)) {
+                                       obit = inv_key_perm[inbit];
+                                       if (obit == 255)
+                                               continue;
+                                       if (obit < 28)
+                                               il |= 0x8000000UL >> obit;
+                                       else
+                                               ir |= 0x8000000UL >> obit-28;
+                               }
+                       }
+                       key_perm_maskl[k][i] = il;
+                       key_perm_maskr[k][i] = ir;
+                       il = 0;
+                       ir = 0;
+                       for (j = 0; j < 7; j++) {
+                               inbit = 7 * k + j;
+                               if (i & (0x80 >> j + 1)) {
+                                       obit = inv_comp_perm[inbit];
+                                       if (obit == 255)
+                                               continue;
+                                       if (obit < 24)
+                                               il |= 0x800000UL >> obit;
+                                       else
+                                               ir |= 0x800000UL >> obit-24;
+                               }
+                       }
+                       comp_maskl[k][i] = il;
+                       comp_maskr[k][i] = ir;
+               }
+       }
+
+       /*
+        * Invert the P-box permutation, and convert into OR-masks for
+        * handling the output of the S-box arrays setup above.
+        */
+       for (i = 0; i < 32; i++)
+               un_pbox[pbox[i] - 1] = (uint8_t)i;
+
+       for (b = 0; b < 4; b++) {
+               for (i = 0; i < 256; i++) {
+                       p = 0;
+                       for (j = 0; j < 8; j++) {
+                               if (i & (0x80 >> j))
+                                       p |= 0x80000000>>un_pbox[8 * b + j];
+                       }
+                       psbox[b][i] = p;
+               }
+       }
+
+       return ctx;
+}
+
+
+static void setup_salt(struct des_ctx *ctx, uint32_t salt)
+{
+       uint32_t obit, saltbit;
+       int i;
+
+       saltbits = 0;
+       saltbit = 1;
+       obit = 0x800000;
+       for (i = 0; i < 24; i++) {
+               if (salt & saltbit)
+                       saltbits |= obit;
+               saltbit <<= 1;
+               obit >>= 1;
+       }
+}
+
+static void des_setkey(struct des_ctx *ctx, const unsigned char *key)
+{
+       uint32_t k0, k1, rawkey0, rawkey1;
+       int shifts, round;
+
+       rawkey0 = key[0]<<24 | key[1]<<16 | key[2]<<8 | key[3];
+       rawkey1 = key[4]<<24 | key[5]<<16 | key[6]<<8 | key[7];
+
+       /*
+        * Do key permutation and split into two 28-bit subkeys.
+        */
+       k0 = key_perm_maskl[0][rawkey0 >> 25]
+          | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
+          | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
+          | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
+          | key_perm_maskl[4][rawkey1 >> 25]
+          | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
+          | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
+          | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
+       k1 = key_perm_maskr[0][rawkey0 >> 25]
+          | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
+          | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
+          | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
+          | key_perm_maskr[4][rawkey1 >> 25]
+          | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
+          | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
+          | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
+       /*
+        * Rotate subkeys and do compression permutation.
+        */
+       shifts = 0;
+       for (round = 0; round < 16; round++) {
+               uint32_t t0, t1;
+
+               shifts += key_shifts[round];
+
+               t0 = (k0 << shifts) | (k0 >> (28 - shifts));
+               t1 = (k1 << shifts) | (k1 >> (28 - shifts));
+
+               en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
+                               | comp_maskl[1][(t0 >> 14) & 0x7f]
+                               | comp_maskl[2][(t0 >> 7) & 0x7f]
+                               | comp_maskl[3][t0 & 0x7f]
+                               | comp_maskl[4][(t1 >> 21) & 0x7f]
+                               | comp_maskl[5][(t1 >> 14) & 0x7f]
+                               | comp_maskl[6][(t1 >> 7) & 0x7f]
+                               | comp_maskl[7][t1 & 0x7f];
+
+               en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
+                               | comp_maskr[1][(t0 >> 14) & 0x7f]
+                               | comp_maskr[2][(t0 >> 7) & 0x7f]
+                               | comp_maskr[3][t0 & 0x7f]
+                               | comp_maskr[4][(t1 >> 21) & 0x7f]
+                               | comp_maskr[5][(t1 >> 14) & 0x7f]
+                               | comp_maskr[6][(t1 >> 7) & 0x7f]
+                               | comp_maskr[7][t1 & 0x7f];
+       }
+}
+
+
+static void do_des(struct des_ctx *ctx, uint32_t *l_out, uint32_t *r_out, int count)
+{
+       uint32_t l, r, *kl, *kr;
+       uint32_t f = f; /* silence gcc */
+       uint32_t r48l, r48r;
+       int round;
+
+       /* Do initial permutation (IP). */
+       l = r = 0;
+
+       do {
+               /* Do each round. */
+               kl = en_keysl;
+               kr = en_keysr;
+               round = 16;
+               do {
+                       /* Expand R to 48 bits (simulate the E-box). */
+                       r48l    = ((r & 0x00000001) << 23)
+                               | ((r & 0xf8000000) >> 9)
+                               | ((r & 0x1f800000) >> 11)
+                               | ((r & 0x01f80000) >> 13)
+                               | ((r & 0x001f8000) >> 15);
+
+                       r48r    = ((r & 0x0001f800) << 7)
+                               | ((r & 0x00001f80) << 5)
+                               | ((r & 0x000001f8) << 3)
+                               | ((r & 0x0000001f) << 1)
+                               | ((r & 0x80000000) >> 31);
+                       /*
+                        * Do salting for crypt() and friends, and
+                        * XOR with the permuted key.
+                        */
+                       f = (r48l ^ r48r) & saltbits;
+                       r48l ^= f ^ *kl++;
+                       r48r ^= f ^ *kr++;
+                       /*
+                        * Do sbox lookups (which shrink it back to 32 bits)
+                        * and do the pbox permutation at the same time.
+                        */
+                       f = psbox[0][m_sbox[0][r48l >> 12]]
+                         | psbox[1][m_sbox[1][r48l & 0xfff]]
+                         | psbox[2][m_sbox[2][r48r >> 12]]
+                         | psbox[3][m_sbox[3][r48r & 0xfff]];
+                       /* Now that we've permuted things, complete f(). */
+                       f ^= l;
+                       l = r;
+                       r = f;
+               } while (--round);
+               r = l;
+               l = f;
+       } while (--count);
+
+       /* Do final permutation (inverse of IP). */
+       *l_out  = fp_maskl[0][l >> 24]
+               | fp_maskl[1][(l >> 16) & 0xff]
+               | fp_maskl[2][(l >> 8) & 0xff]
+               | fp_maskl[3][l & 0xff]
+               | fp_maskl[4][r >> 24]
+               | fp_maskl[5][(r >> 16) & 0xff]
+               | fp_maskl[6][(r >> 8) & 0xff]
+               | fp_maskl[7][r & 0xff];
+       *r_out  = fp_maskr[0][l >> 24]
+               | fp_maskr[1][(l >> 16) & 0xff]
+               | fp_maskr[2][(l >> 8) & 0xff]
+               | fp_maskr[3][l & 0xff]
+               | fp_maskr[4][r >> 24]
+               | fp_maskr[5][(r >> 16) & 0xff]
+               | fp_maskr[6][(r >> 8) & 0xff]
+               | fp_maskr[7][r & 0xff];
+}
+
+#define DES_OUT_BUFSIZE 21
+
+static void
+to64_msb_first(char *s, unsigned v)
+{
+       *s++ = i64c(v >> 18); /* bits 23..18 */
+       *s++ = i64c(v >> 12); /* bits 17..12 */
+       *s++ = i64c(v >> 6); /* bits 11..6 */
+       *s   = i64c(v); /* bits 5..0 */
+}
+
+static char *
+des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
+               const unsigned char *key, const unsigned char *setting)
+{
+       uint32_t salt, r0, r1, keybuf[2];
+       uint8_t *q;
+
+       /*
+        * Copy the key, shifting each character up by one bit
+        * and padding with zeros.
+        */
+       q = (uint8_t *)keybuf;
+       while (q - (uint8_t *)keybuf != 8) {
+               *q = *key << 1;
+               if (*q)
+                       key++;
+               q++;
+       }
+       des_setkey(ctx, (char *)keybuf);
+
+       /*
+        * setting - 2 bytes of salt
+        * key - up to 8 characters
+        */
+       salt = (ascii_to_bin(setting[1]) << 6)
+            |  ascii_to_bin(setting[0]);
+
+       output[0] = setting[0];
+       /*
+        * If the encrypted password that the salt was extracted from
+        * is only 1 character long, the salt will be corrupted.  We
+        * need to ensure that the output string doesn't have an extra
+        * NUL in it!
+        */
+       output[1] = setting[1] ? setting[1] : output[0];
+
+       setup_salt(ctx, salt);
+       /* Do it. */
+       do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */);
+
+       /* Now encode the result. */
+       /* Each call takes low-order 24 bits and stores 4 chars */
+       /* bits 31..8 of r0 */
+       to64_msb_first(output + 2, (r0 >> 8));
+       /* bits 7..0 of r0 and 31..16 of r1 */
+       to64_msb_first(output + 6, (r0 << 16) | (r1 >> 16));
+       /* bits 15..0 of r1 and two zero bits (plus extra zero byte) */
+       to64_msb_first(output + 10, (r1 << 8));
+       /* extra zero byte is encoded as '.', fixing it */
+       output[13] = '\0';
+
+       return output;
+}
+
+#undef C
+#undef init_perm
+#undef final_perm
+#undef m_sbox
+#undef D
+#undef const_ctx
+#undef saltbits
+#undef old_salt
+#undef old_rawkey0
+#undef old_rawkey1
+#undef un_pbox
+#undef inv_comp_perm
+#undef inv_key_perm
+#undef en_keysl
+#undef en_keysr
+#undef de_keysl
+#undef de_keysr
+#undef ip_maskl
+#undef ip_maskr
+#undef fp_maskl
+#undef fp_maskr
+#undef key_perm_maskl
+#undef key_perm_maskr
+#undef comp_maskl
+#undef comp_maskr
+#undef psbox
+
+struct crypt_data;
+
+char *__crypt_r(const char *clear, const char *salt, struct crypt_data *data)
+{
+       struct des_ctx des_ctx = { 0 };
+
+#if 0
+       /* MD5 or SHA? */
+       if (salt[0] == '$' && salt[1] && salt[2] == '$') {
+               if (salt[1] == '1')
+                       return md5_crypt((char *)data, clear, salt);
+       }
+#endif
+
+       des_init(&des_ctx);
+       return des_crypt(&des_ctx, (char *)data, clear, salt);
+}
+
+weak_alias(__crypt_r, crypt_r);
+
+char *crypt(const char *clear, const char *salt)
+{
+       static char buf[128];
+       return __crypt_r(clear, salt, (void *)buf);
+}
diff --git a/src/misc/cuserid.c b/src/misc/cuserid.c
new file mode 100644 (file)
index 0000000..8ad0b9f
--- /dev/null
@@ -0,0 +1,13 @@
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+
+char *cuserid(char *buf)
+{
+       struct passwd pw, *ppw;
+       long pwb[256];
+       if (getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw))
+               return 0;
+       snprintf(buf, L_cuserid, "%s", pw.pw_name);
+       return buf;
+}
diff --git a/src/misc/dirname.c b/src/misc/dirname.c
new file mode 100644 (file)
index 0000000..8f70dbb
--- /dev/null
@@ -0,0 +1,15 @@
+#include <string.h>
+#include <libgen.h>
+
+char *dirname(char *s)
+{
+       size_t i;
+       if (!s || !*s || !strchr(s, '/')) return ".";
+       i = strlen(s)-1;
+       for (; i&&s[i]=='/'; i--);
+       for (; i&&s[i-1]!='/'; i--);
+       for (; i&&s[i-1]=='/'; i--);
+       if (!i && *s=='/') i++;
+       s[i] = 0;
+       return s;
+}
diff --git a/src/misc/ffs.c b/src/misc/ffs.c
new file mode 100644 (file)
index 0000000..2f7cb32
--- /dev/null
@@ -0,0 +1,9 @@
+#include <strings.h>
+
+int ffs(int i)
+{
+       unsigned int j = i;
+       for (i=1; j && !(j&1); j>>=1, i++);
+       if (j) return i;
+       return 0;
+}
diff --git a/src/misc/ftw.c b/src/misc/ftw.c
new file mode 100644 (file)
index 0000000..de01e39
--- /dev/null
@@ -0,0 +1,9 @@
+#include <ftw.h>
+#include "libc.h"
+
+int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int fd_limit)
+{
+       return nftw(path, (void *)fn, fd_limit, FTW_PHYS);
+}
+
+LFS64(ftw);
diff --git a/src/misc/getdomainname.c b/src/misc/getdomainname.c
new file mode 100644 (file)
index 0000000..7eb113d
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <string.h>
+
+int getdomainname(char *name, size_t len)
+{
+       *name = 0;
+       return 0;
+}
diff --git a/src/misc/getgrouplist.c b/src/misc/getgrouplist.c
new file mode 100644 (file)
index 0000000..88f273d
--- /dev/null
@@ -0,0 +1,11 @@
+#include <grp.h>
+
+/* FIXME */
+
+int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
+{
+       if (*ngroups<1) return -1;
+       *groups = gid;
+       *ngroups = 1;
+       return 0;
+}
diff --git a/src/misc/getopt.c b/src/misc/getopt.c
new file mode 100644 (file)
index 0000000..abf0e84
--- /dev/null
@@ -0,0 +1,63 @@
+#include <unistd.h>
+#include <wchar.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+
+char *optarg;
+int optind=1, opterr=1, optopt;
+static int optpos;
+
+int getopt(int argc, char * const argv[], const char *optstring)
+{
+       int i;
+       wchar_t c, d;
+       int k, l;
+       char *optchar;
+
+       if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || !argv[optind][1])
+               return -1;
+       if (argv[optind][1] == '-' && !argv[optind][2])
+               return optind++, -1;
+
+       if (!optpos) optpos++;
+       if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
+               k = 1;
+               c = 0xfffd; /* replacement char */
+       }
+       optchar = argv[optind]+optpos;
+       optopt = c;
+       optpos += k;
+
+       if (!argv[optind][optpos]) {
+               optind++;
+               optpos = 0;
+       }
+
+       for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1);
+
+       if (d != c) {
+               if (optstring[0] != ':' && opterr) {
+                       write(2, argv[0], strlen(argv[0]));
+                       write(2, ": illegal option: ", 18);
+                       write(2, optchar, k);
+                       write(2, "\n", 1);
+               }
+               return '?';
+       }
+       if (optstring[i+1] == ':') {
+               if (optind >= argc) {
+                       if (optstring[0] == ':') return ':';
+                       if (opterr) {
+                               write(2, argv[0], strlen(argv[0]));
+                               write(2, ": option requires an argument: ", 31);
+                               write(2, optchar, k);
+                               write(2, "\n", 1);
+                       }
+                       return '?';
+               }
+               optarg = argv[optind++] + optpos;
+               optpos = 0;
+       }
+       return c;
+}
diff --git a/src/misc/getpriority.c b/src/misc/getpriority.c
new file mode 100644 (file)
index 0000000..2fb26b2
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/resource.h>
+#include "syscall.h"
+
+int getpriority(int which, id_t who)
+{
+       int ret = syscall2(__NR_getpriority, which, who);
+       if (ret < 0) return ret;
+       return 20-ret;
+}
diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c
new file mode 100644 (file)
index 0000000..db25943
--- /dev/null
@@ -0,0 +1,15 @@
+#include <sys/resource.h>
+#include "syscall.h"
+#include "libc.h"
+
+int getrlimit(int resource, struct rlimit *rlim)
+{
+       long k_rlim[2];
+       if (syscall2(__NR_ugetrlimit, resource, (long)k_rlim) < 0)
+               return -1;
+       rlim->rlim_cur = k_rlim[0];
+       rlim->rlim_max = k_rlim[1];
+       return 0;
+}
+
+LFS64(getrlimit);
diff --git a/src/misc/getrusage.c b/src/misc/getrusage.c
new file mode 100644 (file)
index 0000000..1b8850f
--- /dev/null
@@ -0,0 +1,20 @@
+#include <sys/resource.h>
+#include <string.h>
+#include "syscall.h"
+
+/* this is a huge hack to make up for the kernel's stupid 32bit time_t
+ * without having to recopy the whole rusage structure ourselves.. */
+
+int getrusage(int who, struct rusage *ru)
+{
+       struct { long tv_sec, tv_usec; } ktv[2];
+       char *fakeaddr = ((char *)ru + sizeof(struct timeval [2]) - sizeof ktv);
+       if (syscall2(__NR_getrusage, who, (long)fakeaddr) < 0)
+               return -1;
+       memcpy(ktv, fakeaddr, sizeof ktv);
+       ru->ru_utime.tv_sec  = ktv[0].tv_sec;
+       ru->ru_utime.tv_usec = ktv[0].tv_usec;
+       ru->ru_stime.tv_sec  = ktv[1].tv_sec;
+       ru->ru_stime.tv_usec = ktv[1].tv_usec;
+       return 0;
+}
diff --git a/src/misc/getsubopt.c b/src/misc/getsubopt.c
new file mode 100644 (file)
index 0000000..dac9bf9
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include <string.h>
+
+int getsubopt(char **opt, char *const *keys, char **val)
+{
+       char *s = *opt;
+       int i;
+
+       *val = NULL;
+       *opt = strchr(s, ',');
+       if (*opt) *(*opt)++ = 0;
+       else *opt = s + strlen(s);
+
+       for (i=0; keys[i]; i++) {
+               size_t l = strlen(keys[i]);
+               if (strncmp(keys[i], s, l)) continue;
+               if (s[l] == '=')
+                       *val = s + l;
+               else if (s[l]) continue;
+               return i;
+       }
+       return -1;
+}
diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c
new file mode 100644 (file)
index 0000000..808b7c9
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/ioctl.h>
+#include <stdarg.h>
+#include "syscall.h"
+
+int ioctl(int fd, int req, ...)
+{
+       void *arg;
+       va_list ap;
+       va_start(ap, req);
+       arg = va_arg(ap, void *);
+       va_end(ap);
+       return syscall3(__NR_ioctl, fd, req, (long)arg);
+}
diff --git a/src/misc/lockf.c b/src/misc/lockf.c
new file mode 100644 (file)
index 0000000..d8f82ef
--- /dev/null
@@ -0,0 +1,33 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "libc.h"
+
+int lockf(int fd, int op, off_t size)
+{
+       struct flock l = {
+               .l_type = F_WRLCK,
+               .l_whence = SEEK_CUR,
+               .l_len = size,
+       };
+       switch (op) {
+       case F_TEST:
+               l.l_type = F_RDLCK;
+               if (fcntl(fd, F_GETLK, &l) < 0)
+                       return -1;
+               if (l.l_type == F_UNLCK || l.l_pid == getpid())
+                       return 0;
+               errno = EACCES;
+               return -1;
+       case F_ULOCK:
+               l.l_type = F_UNLCK;
+       case F_TLOCK:
+               return fcntl(fd, F_SETLK, &l);
+       case F_LOCK:
+               return fcntl(fd, F_SETLKW, &l);
+       }
+       errno = EINVAL;
+       return -1;
+}
+
+LFS64(lockf);
diff --git a/src/misc/nftw.c b/src/misc/nftw.c
new file mode 100644 (file)
index 0000000..1b94ac1
--- /dev/null
@@ -0,0 +1,121 @@
+#include <ftw.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include "libc.h"
+
+struct history
+{
+       struct history *chain;
+       dev_t dev;
+       ino_t ino;
+       int level;
+       int base;
+};
+
+#undef dirfd
+#define dirfd(d) (*(int *)d)
+
+static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
+{
+       size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
+       struct stat st;
+       struct history new;
+       int type;
+       int r;
+       struct FTW lev;
+       char *name;
+
+       if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
+               if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
+                       type = FTW_SLN;
+               else if (errno != EACCES) return -1;
+               else type = FTW_NS;
+       } else if (S_ISDIR(st.st_mode)) {
+               if (access(path, R_OK) < 0) type = FTW_DNR;
+               else if (flags & FTW_DEPTH) type = FTW_DP;
+               else type = FTW_D;
+       } else if (S_ISLNK(st.st_mode)) {
+               if (flags & FTW_PHYS) type = FTW_SL;
+               else type = FTW_SLN;
+       } else {
+               type = FTW_F;
+       }
+
+       if ((flags & FTW_MOUNT) && h
+        && (st.st_dev != h->dev || st.st_ino != h->ino))
+               return 0;
+       
+       new.chain = h;
+       new.dev = st.st_dev;
+       new.ino = st.st_ino;
+       new.level = h ? h->level+1 : 0;
+       new.base = l+1;
+       
+       lev.level = new.level;
+       lev.base = h ? h->base : (name=strrchr(path, '/')) ? name-path : 0;
+
+       if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
+               return r;
+
+       for (; h; h = h->chain)
+               if (h->dev == st.st_dev && h->ino == st.st_ino)
+                       return 0;
+
+       if ((type == FTW_D || type == FTW_DP) && fd_limit) {
+               DIR *d = opendir(path);
+               if (d) {
+                       struct dirent *de;
+                       while ((de = readdir(d))) {
+                               if (de->d_name[0] == '.'
+                                && (!de->d_name[1]
+                                 || (de->d_name[1]=='.'
+                                  && !de->d_name[2]))) continue;
+                               if (strlen(de->d_name) >= PATH_MAX-l) {
+                                       errno = ENAMETOOLONG;
+                                       closedir(d);
+                                       return -1;
+                               }
+                               path[j]='/';
+                               strcpy(path+j+1, de->d_name);
+                               if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
+                                       closedir(d);
+                                       return r;
+                               }
+                       }
+                       closedir(d);
+               } else if (errno != EACCES) {
+                       return -1;
+               }
+       }
+
+       path[l] = 0;
+       if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
+               return r;
+
+       return 0;
+}
+
+int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
+{
+       size_t l;
+       char pathbuf[PATH_MAX+1];
+
+       if (fd_limit <= 0) return 0;
+
+       l = strlen(path);
+       if (l > PATH_MAX) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       memcpy(pathbuf, path, l+1);
+       
+       return do_nftw(pathbuf, fn, fd_limit, flags, NULL);
+}
+
+LFS64(nftw);
diff --git a/src/misc/openpty.c b/src/misc/openpty.c
new file mode 100644 (file)
index 0000000..0b4eb22
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pty.h>
+#include <stdio.h>
+
+/* Nonstandard, but vastly superior to the standard functions */
+
+int openpty(int *m, int *s, char *name, const struct termios *tio, const struct winsize *ws)
+{
+       int n=0;
+       char buf[20];
+
+       *m = open("/dev/ptmx", O_RDWR|O_NOCTTY);
+       if (!*m) return -1;
+
+       if (ioctl(*m, TIOCSPTLCK, &n) || ioctl (*m, TIOCGPTN, &n)) {
+               close(*m);
+               return -1;
+       }
+
+       if (!name) name = buf;
+       snprintf(name, sizeof buf, "/dev/pts/%d", n);
+       if ((*s = open(name, O_RDWR|O_NOCTTY)) < 0) {
+               close(*m);
+               return -1;
+       }
+
+       if (tio) tcsetattr(*s, TCSANOW, tio);
+       if (ws) ioctl(*s, TIOCSWINSZ, ws);
+
+       return 0;
+}
diff --git a/src/misc/pty.c b/src/misc/pty.c
new file mode 100644 (file)
index 0000000..0d25a83
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+int posix_openpt(int flags)
+{
+       return open("/dev/ptmx", flags);
+}
+
+int grantpt(int fd)
+{
+       return 0;
+}
+
+int unlockpt(int fd)
+{
+       int unlock = 0;
+       return ioctl(fd, TIOCSPTLCK, &unlock);
+}
+
+char *ptsname(int fd)
+{
+       static char buf[9 + sizeof(int)*3 + 1];
+       char *s = buf+sizeof(buf)-1;
+       int pty;
+       if (ioctl (fd, TIOCGPTN, &pty))
+               return NULL;
+       if (pty) for (; pty; pty/=10) *--s = '0' + pty%10;
+       else *--s = '0';
+       s -= 9;
+        s[0] = '/'; s[1] = 'd'; s[2] = 'e'; s[3] = 'v';
+       s[4] = '/'; s[5] = 'p'; s[6] = 't'; s[7] = 's'; s[8] = '/';
+       return s;
+}
diff --git a/src/misc/realpath.c b/src/misc/realpath.c
new file mode 100644 (file)
index 0000000..f6b5549
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+char *realpath(const char *filename, char *resolved)
+{
+       return 0;
+}
diff --git a/src/misc/sched_yield.c b/src/misc/sched_yield.c
new file mode 100644 (file)
index 0000000..8a68519
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sched.h>
+#include "syscall.h"
+#include "libc.h"
+
+int __yield()
+{
+       return syscall0(__NR_sched_yield);
+}
+
+weak_alias(__yield, sched_yield);
diff --git a/src/misc/setpriority.c b/src/misc/setpriority.c
new file mode 100644 (file)
index 0000000..26da4b8
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/resource.h>
+#include "syscall.h"
+
+int setpriority(int which, id_t who, int prio)
+{
+       return syscall3(__NR_getpriority, which, who, prio);
+}
diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c
new file mode 100644 (file)
index 0000000..7fdfc4e
--- /dev/null
@@ -0,0 +1,11 @@
+#include <sys/resource.h>
+#include "syscall.h"
+#include "libc.h"
+
+int setrlimit(int resource, const struct rlimit *rlim)
+{
+       long k_rlim[2] = { rlim->rlim_cur, rlim->rlim_max };
+       return syscall2(__NR_setrlimit, resource, (long)k_rlim);
+}
+
+LFS64(setrlimit);
diff --git a/src/misc/syslog.c b/src/misc/syslog.c
new file mode 100644 (file)
index 0000000..4809d2d
--- /dev/null
@@ -0,0 +1,115 @@
+#include <stdarg.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include "libc.h"
+
+static int lock;
+static const char *log_ident;
+static int log_opt;
+static int log_facility = LOG_USER;
+static int log_mask = 0xff;
+static FILE *log_f;
+
+int setlogmask(int maskpri)
+{
+       int old = log_mask;
+       if (maskpri) log_mask = maskpri;
+       return old;
+}
+
+static const struct {
+       short sun_family;
+       char sun_path[9];
+} log_addr = {
+       AF_UNIX,
+       "/dev/log"
+};
+
+void closelog(void)
+{
+       LOCK(&lock);
+       if (log_f) fclose(log_f);
+       log_f = NULL;
+       UNLOCK(&lock);
+}
+
+static void __openlog(const char *ident, int opt, int facility)
+{
+       int fd;
+
+       log_ident = ident;
+       log_opt = opt;
+       log_facility = facility;
+
+       if (!(opt & LOG_NDELAY) || log_f) return;
+
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       fcntl(fd, F_SETFD, FD_CLOEXEC);
+       if (connect(fd, (void *)&log_addr, sizeof(short) + sizeof "/dev/log") < 0)
+               close(fd);
+       else log_f = fdopen(fd, "wb");
+}
+
+void openlog(const char *ident, int opt, int facility)
+{
+       LOCK(&lock);
+       __openlog(ident, opt, facility);
+       UNLOCK(&lock);
+}
+
+void syslog(int priority, const char *message, ...)
+{
+       struct sigaction sa;
+       va_list ap;
+       char timebuf[16];
+       time_t now;
+       struct tm tm;
+       //const char *fmt, *ident, *sep;
+       //int i;
+
+       if (!(log_mask & LOG_MASK(priority&7)) || (priority&~0x3ff)) return;
+
+       LOCK(&lock);
+
+       if (!log_f) __openlog(log_ident, log_opt | LOG_NDELAY, log_facility);
+       if (!log_f) {
+               UNLOCK(&lock);
+               return;
+       }
+
+       memset(&sa, 0, sizeof sa);
+       sa.sa_handler = SIG_IGN;
+       if (sigaction(SIGPIPE, &sa, &sa) < 0) {
+               // we must abandon logging or we might cause SIGPIPE
+               UNLOCK(&lock);
+               return;
+       }
+
+       now = time(NULL);
+       gmtime_r(&now, &tm);
+       strftime(timebuf, sizeof timebuf, "%b %e %T", &tm);
+
+       fprintf(log_f, "<%d>%s ", priority, timebuf);
+       if (log_ident) fprintf(log_f, "%s", log_ident);
+       if (log_opt & LOG_PID) fprintf(log_f, "[%d]", getpid());
+       if (log_ident) fprintf(log_f, ": ");
+
+       va_start(ap, message);
+       vfprintf(log_f, message, ap);
+       va_end(ap);
+       fputc(0, log_f);
+       fflush(log_f);
+
+       // Note: LOG_CONS is not supported because it is annoying!!
+       // syslogd will send messages to console if it deems them appropriate!
+
+       sigaction(SIGPIPE, &sa, NULL);
+
+       UNLOCK(&lock);
+}
diff --git a/src/misc/uname.c b/src/misc/uname.c
new file mode 100644 (file)
index 0000000..fbe8664
--- /dev/null
@@ -0,0 +1,8 @@
+#include <sys/utsname.h>
+#include <string.h>
+#include "syscall.h"
+
+int uname(struct utsname *uts)
+{
+       return syscall1(__NR_uname, (long)uts);
+}
diff --git a/src/mman/madvise.c b/src/mman/madvise.c
new file mode 100644 (file)
index 0000000..f03647c
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/mman.h>
+#include "syscall.h"
+#include "libc.h"
+
+int __madvise(void *addr, size_t len, int advice)
+{
+       return syscall3(__NR_madvise, (long)addr, len, advice);
+}
+
+weak_alias(__madvise, madvise);
diff --git a/src/mman/mlock.c b/src/mman/mlock.c
new file mode 100644 (file)
index 0000000..3c7c653
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/mman.h>
+#include "syscall.h"
+
+int mlock(const void *addr, size_t len)
+{
+       return syscall2(__NR_mlock, (long)addr, len);
+}
diff --git a/src/mman/mlockall.c b/src/mman/mlockall.c
new file mode 100644 (file)
index 0000000..782fc9d
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/mman.h>
+#include "syscall.h"
+
+int mlockall(int flags)
+{
+       return syscall1(__NR_mlockall, flags);
+}
diff --git a/src/mman/mmap.c b/src/mman/mmap.c
new file mode 100644 (file)
index 0000000..93c7658
--- /dev/null
@@ -0,0 +1,18 @@
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <limits.h>
+#include "syscall.h"
+#include "libc.h"
+
+void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
+{
+       if (sizeof(off_t) > sizeof(long))
+               if (((long)off & 0xfff) | ((long)((unsigned long long)off>>(12 + 8*(sizeof(off_t)-sizeof(long))))))
+                       start = (void *)-1;
+       return (void *)syscall6(__NR_mmap2, (long)start, len, prot, flags, fd, off>>12);
+}
+
+weak_alias(__mmap, mmap);
+
+LFS64(mmap);
diff --git a/src/mman/mprotect.c b/src/mman/mprotect.c
new file mode 100644 (file)
index 0000000..11d5e23
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/mman.h>
+#include "syscall.h"
+
+int mprotect(void *addr, size_t len, int prot)
+{
+       return syscall3(__NR_mprotect, (long)addr, len, prot);
+}
diff --git a/src/mman/mremap.c b/src/mman/mremap.c
new file mode 100644 (file)
index 0000000..78491ef
--- /dev/null
@@ -0,0 +1,19 @@
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdarg.h>
+#include "syscall.h"
+#include "libc.h"
+
+void *__mremap(void *old_addr, size_t old_len, size_t new_len, int flags, ...)
+{
+       va_list ap;
+       void *new_addr;
+       
+       va_start(ap, flags);
+       new_addr = va_arg(ap, void *);
+       va_end(ap);
+
+       return (void *)syscall5(__NR_mremap, (long)old_addr, old_len, new_len, flags, (long)new_addr);
+}
+
+weak_alias(__mremap, mremap);
diff --git a/src/mman/msync.c b/src/mman/msync.c
new file mode 100644 (file)
index 0000000..e092647
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <sys/mman.h>
+#include "syscall.h"
+
+int msync(void *start, size_t len, int flags)
+{
+       return syscall3(__NR_msync, (long)start, len, flags);
+}
diff --git a/src/mman/munlock.c b/src/mman/munlock.c
new file mode 100644 (file)
index 0000000..0db5981
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/mman.h>
+#include "syscall.h"
+
+int munlock(const void *addr, size_t len)
+{
+       return syscall2(__NR_munlock, (long)addr, len);
+}
diff --git a/src/mman/munlockall.c b/src/mman/munlockall.c
new file mode 100644 (file)
index 0000000..ce3e86c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/mman.h>
+#include "syscall.h"
+
+int munlockall(void)
+{
+       return syscall0(__NR_munlockall);
+}
diff --git a/src/mman/munmap.c b/src/mman/munmap.c
new file mode 100644 (file)
index 0000000..c9661cd
--- /dev/null
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <sys/mman.h>
+#include "syscall.h"
+#include "libc.h"
+
+int __munmap(void *start, size_t len)
+{
+       return syscall2(__NR_munmap, (long)start, len);
+}
+
+weak_alias(__munmap, munmap);
diff --git a/src/mman/posix_madvise.c b/src/mman/posix_madvise.c
new file mode 100644 (file)
index 0000000..4727ad7
--- /dev/null
@@ -0,0 +1,6 @@
+#include <sys/mman.h>
+
+int posix_madvise(void *addr, size_t len, int advice)
+{
+       return 0;
+}
diff --git a/src/multibyte/btowc.c b/src/multibyte/btowc.c
new file mode 100644 (file)
index 0000000..9d2c3b1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <wchar.h>
+
+wint_t btowc(int c)
+{
+       return c<128U ? c : EOF;
+}
diff --git a/src/multibyte/decode.c b/src/multibyte/decode.c
new file mode 100644 (file)
index 0000000..8d3d3c0
--- /dev/null
@@ -0,0 +1,47 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+/* Decodes UTF-8 byte-by-byte. The c argument must be initialized to 0
+ * to begin decoding; when finished it will contain the Unicode scalar
+ * value decoded. Return value is 1 if finished, 0 if in-progress, and
+ * -1 if an invalid sequence was encountered. After an invalid sequence,
+ * the state (in c) automatically resets to 0 if a continuation byte was
+ * expected to facilitate a calling idiom of immediately retrying a
+ * failed decode call after processing the invalid sequence. If the
+ * second try fails, the byte is invalid as a starter as well.
+ *
+ * A trivial usage idiom is:
+ *       while (src<end && (n=decode(dst, *src))>=0) 1[dst+=n]=0, src++;
+ */
+
+int decode(unsigned *c, unsigned b)
+{
+       if (!*c) {
+               if (b < 0x80) {
+                       *c = b;
+                       return 1;
+               } else if (b-SA >= SB-SA) {
+                       *c = FAILSTATE;
+                       return -1;
+               }
+               *c = bittab[b-SA];
+               return 0;
+       }
+
+       if (OOB(*c,b)) {
+               *c = 0;
+               return -1;
+       }
+       *c = *c<<6 | b-0x80;
+       return !(*c&(1U<<31));
+}
diff --git a/src/multibyte/internal.c b/src/multibyte/internal.c
new file mode 100644 (file)
index 0000000..e9b938d
--- /dev/null
@@ -0,0 +1,60 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <inttypes.h>
+
+#include "internal.h"
+
+#define C(x) ( x<2 ? -1 : ( R(0x80,0xc0) | x ) )
+#define D(x) C((x+16))
+#define E(x) ( ( x==0 ? R(0xa0,0xc0) : \
+                 x==0xd ? R(0x80,0xa0) : \
+                 R(0x80,0xc0) ) \
+             | ( R(0x80,0xc0) >> 6 ) \
+             | x )
+#ifdef I_FAILED_TO_RTFM_RFC3629
+#define F0(x) (( x==0 ? R(0x90,0xc0) : \
+                 R(0x80,0xc0) ) \
+             | ( R(0x80,0xc0) >> 6 ) \
+             | ( R(0x80,0xc0) >> 12 ) \
+             | x )
+#define F8(x) (( x==0 ? R(0xa0,0xc0) : \
+                 R(0x80,0xc0) ) \
+             | ( R(0x80,0xc0) >> 6 ) \
+             | ( R(0x80,0xc0) >> 12 ) \
+             | ( R(0x80,0xc0) >> 18 ) \
+             | x )
+#define FC(x) (( x==0 ? R(0x88,0xc0) : \
+                 R(0x80,0xc0) ) \
+             | ( R(0x80,0xc0) >> 6 ) \
+             | ( R(0x80,0xc0) >> 12 ) \
+             | ( R(0x80,0xc0) >> 18 ) \
+             | ( R(0x80,0xc0) >> 24 ) \
+             | x )
+#define F(x) ( x<8 ? F0(x) : x<12 ? F8((x&3)) : x<14 ? FC((x&1)) : -1 )
+#else
+#define F(x) ( ( x>=5 ? 0 : \
+                 x==0 ? R(0x90,0xc0) : \
+                 x==4 ? R(0x80,0xa0) : \
+                 R(0x80,0xc0) ) \
+             | ( R(0x80,0xc0) >> 6 ) \
+             | ( R(0x80,0xc0) >> 12 ) \
+             | x )
+#endif
+
+const uint32_t bittab[] = {
+                     C(0x2),C(0x3),C(0x4),C(0x5),C(0x6),C(0x7),
+       C(0x8),C(0x9),C(0xa),C(0xb),C(0xc),C(0xd),C(0xe),C(0xf),
+       D(0x0),D(0x1),D(0x2),D(0x3),D(0x4),D(0x5),D(0x6),D(0x7),
+       D(0x8),D(0x9),D(0xa),D(0xb),D(0xc),D(0xd),D(0xe),D(0xf),
+       E(0x0),E(0x1),E(0x2),E(0x3),E(0x4),E(0x5),E(0x6),E(0x7),
+       E(0x8),E(0x9),E(0xa),E(0xb),E(0xc),E(0xd),E(0xe),E(0xf),
+       F(0x0),F(0x1),F(0x2),F(0x3),F(0x4),
+#ifdef I_FAILED_TO_RTFM_RFC3629
+                                          F(0x5),F(0x6),F(0x7),
+       F(0x8),F(0x9),F(0xa),F(0xb),F(0xc),F(0xd)
+#endif
+};
diff --git a/src/multibyte/internal.h b/src/multibyte/internal.h
new file mode 100644 (file)
index 0000000..427519a
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#define LIBC
+#ifndef LIBC
+/* rename functions not to conflict with libc */
+#ifndef myprefix
+#define myprefix fsmu8_
+#endif
+#define concat2(a,b) a ## b
+#define concat(a,b) concat2(a,b)
+#define prefix(b) concat(myprefix,b)
+
+#undef mblen
+#undef mbrlen
+#undef mbrtowc
+#undef mbsinit
+#undef mbsnrtowcs
+#undef mbsrtowcs
+#undef wcrtomb
+#undef wcsrtombs
+#undef wcstombs
+#undef wctomb
+#define mblen prefix(mblen)
+#define mbrlen prefix(mbrlen)
+#define mbrtowc prefix(mbrtowc)
+#define mbsinit prefix(mbsinit)
+#define mbsnrtowcs prefix(mbsnrtowcs)
+#define mbsrtowcs prefix(mbsrtowcs)
+#define mbstowcs prefix(mbstowcs)
+#define wcrtomb prefix(wcrtomb)
+#define wcsnrtombs prefix(wcsnrtombs)
+#define wcsrtombs prefix(wcsrtombs)
+#define wcstombs prefix(wcstombs)
+#define wctomb prefix(wctomb)
+
+#define bittab prefix(bittab)
+#else
+#define bittab __fsmu8
+#endif
+
+extern const uint32_t bittab[];
+
+/* Upper 6 state bits are a negative integer offset to bound-check next byte */
+/*    equivalent to: ( (b-0x80) | (b+offset) ) & ~0x3f      */
+#define OOB(c,b) (((((b)>>3)-0x10)|(((b)>>3)+((int32_t)(c)>>26))) & ~7)
+
+/* Interval [a,b). Either a must be 80 or b must be c0, lower 3 bits clear. */
+#define R(a,b) ((uint32_t)((a==0x80 ? 0x40-b : -a) << 23))
+#define FAILSTATE R(0x80,0x80)
+
+#ifdef I_FAILED_TO_RTFM_RFC3629
+#define SA 0xc2
+#define SB 0xfe
+#else
+#define SA 0xc2
+#define SB 0xf5
+#endif
diff --git a/src/multibyte/mblen.c b/src/multibyte/mblen.c
new file mode 100644 (file)
index 0000000..26d3564
--- /dev/null
@@ -0,0 +1,17 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+int mblen(const char *s, size_t n)
+{
+       return mbtowc(0, s, n);
+}
diff --git a/src/multibyte/mbrlen.c b/src/multibyte/mbrlen.c
new file mode 100644 (file)
index 0000000..c9a9f03
--- /dev/null
@@ -0,0 +1,18 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t mbrlen(const char *s, size_t n, mbstate_t *st)
+{
+       static unsigned internal;
+       return mbrtowc(0, s, n, st ? st : (mbstate_t *)&internal);
+}
diff --git a/src/multibyte/mbrtowc.c b/src/multibyte/mbrtowc.c
new file mode 100644 (file)
index 0000000..09badeb
--- /dev/null
@@ -0,0 +1,58 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t mbrtowc(wchar_t *wc, const char *src, size_t n, mbstate_t *st)
+{
+       static unsigned internal_state;
+       unsigned c;
+       const unsigned char *s = src;
+       const unsigned N = n;
+
+       if (!st) st = (void *)&internal_state;
+       c = *(unsigned *)st;
+       
+       if (!s) {
+               s = "";
+               wc = (void *)&wc;
+               n = 1;
+       } else if (!wc) wc = (void *)&wc;
+
+       if (!n) return -2;
+       if (!c) {
+               if ((unsigned)*s < 0x80) return !!(*wc = *s);
+               if ((unsigned)*s-SA > SB-SA) goto ilseq;
+               c = bittab[*s++-SA]; n--;
+       }
+
+       if (n) {
+               if (OOB(c,*s)) goto ilseq;
+loop:
+               c = c<<6 | *s++-0x80; n--;
+               if (!(c&(1U<<31))) {
+                       *(unsigned *)st = 0;
+                       *wc = c;
+                       return N-n;
+               }
+               if (n) {
+                       if ((unsigned)*s-0x80 >= 0x40) goto ilseq;
+                       goto loop;
+               }
+       }
+
+       *(unsigned *)st = c;
+       return -2;
+ilseq:
+       *(unsigned *)st = FAILSTATE;
+       errno = EILSEQ;
+       return -1;
+}
diff --git a/src/multibyte/mbsinit.c b/src/multibyte/mbsinit.c
new file mode 100644 (file)
index 0000000..d307e5a
--- /dev/null
@@ -0,0 +1,17 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+int mbsinit(const mbstate_t *st)
+{
+       return !*(unsigned *)st;
+}
diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c
new file mode 100644 (file)
index 0000000..c6f0207
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "internal.h"
+
+size_t mbsnrtowcs(wchar_t *wcs, const char **src, size_t n, size_t wn, mbstate_t *st)
+{
+       size_t l, cnt=0, n2;
+       wchar_t *ws, wbuf[256];
+       const char *s = *src;
+
+       if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf;
+       else ws = wcs;
+
+       /* making sure output buffer size is at most n/4 will ensure
+        * that mbsrtowcs never reads more than n input bytes. thus
+        * we can use mbsrtowcs as long as it's practical.. */
+
+       while ( s && wn && ( (n2=n/4)>=wn || n2>32 ) ) {
+               if (n2>=wn) n2=wn;
+               n -= n2;
+               l = mbsrtowcs(ws, &s, n2, st);
+               if (!(l+1)) {
+                       cnt = l;
+                       wn = 0;
+                       break;
+               }
+               if (ws != wbuf) {
+                       ws += l;
+                       wn -= l;
+               }
+               cnt += l;
+       }
+       if (s) while (wn && n) {
+               l = mbrtowc(ws, s, n, st);
+               if (l+2<=2) {
+                       if (!(l+1)) {
+                               cnt = l;
+                               break;
+                       }
+                       /* have to roll back partial character */
+                       *(unsigned *)st = 0;
+                       break;
+               }
+               s += l; n -= l;
+               /* safe - this loop runs fewer than sizeof(wbuf)/8 times */
+               ws++; wn--;
+               cnt++;
+       }
+       if (wcs) *src = s;
+       return cnt;
+}
diff --git a/src/multibyte/mbsrtowcs.c b/src/multibyte/mbsrtowcs.c
new file mode 100644 (file)
index 0000000..e2b4348
--- /dev/null
@@ -0,0 +1,121 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t mbsrtowcs(wchar_t *ws, const char **src, size_t wn, mbstate_t *st)
+{
+       unsigned c;
+       const unsigned char *s = *src;
+       const wchar_t *wsorig = ws;
+
+       if (!st) st = (void *)&c, c = 0;
+       else c = *(unsigned *)st;
+
+       if (c) {
+               *(unsigned *)st = 0;
+               if (!ws) {
+                       wn = 0;
+                       goto resume0;
+               }
+               goto resume;
+       }
+
+       if (!ws) for (wn=0;;) {
+               if ((unsigned)*s-SA >= SB-SA) {
+                       while (((unsigned)s&3) && (unsigned)*s-1<0x7f) s++, wn++;
+                       while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) s+=4, wn+=4;
+                       while ((unsigned)*s-1<0x7f) s++, wn++;
+                       if (!*s) return wn;
+                       if ((unsigned)*s-SA >= SB-SA) goto ilseq2;
+               }
+               c = bittab[*s++-SA];
+               do {
+resume0:
+                       if (OOB(c,*s)) goto ilseq2; s++;
+                       c <<= 6; if (!(c&(1U<<31))) break;
+#ifdef I_FAILED_TO_RTFM_RFC3629
+                       if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2;
+                       c <<= 6; if (!(c&(1U<<31))) break;
+                       if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2;
+                       c <<= 6; if (!(c&(1U<<31))) break;
+#endif
+                       if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2;
+                       c <<= 6; if (!(c&(1U<<31))) break;
+                       if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2;
+               } while (0);
+               wn++; c = 0;
+       }
+
+       while (wn) {
+               if ((unsigned)*s-SA >= SB-SA) {
+                       if (wn >= 7) {
+                               while (((unsigned)s&3) && (unsigned)*s-1<0x7f) {
+                                       *ws++ = *s++;
+                                       wn--;
+                               }
+                               while (wn>=4 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
+                                       *ws++ = *s++;
+                                       *ws++ = *s++;
+                                       *ws++ = *s++;
+                                       *ws++ = *s++;
+                                       wn -= 4;
+                               }
+                       }
+                       while (wn && (unsigned)*s-1<0x7f) {
+                               *ws++ = *s++;
+                               wn--;
+                       }
+                       if (!wn) break;
+                       if (!*s) {
+                               *ws = 0;
+                               *src = 0;
+                               return ws-wsorig;
+                       }
+                       if ((unsigned)*s-SA >= SB-SA) goto ilseq;
+               }
+               c = bittab[*s++-SA];
+               do {
+resume:
+                       if (OOB(c,*s)) goto ilseq;
+                       c = (c<<6) | *s++-0x80;
+                       if (!(c&(1U<<31))) break;
+
+#ifdef I_FAILED_TO_RTFM_RFC3629
+                       if ((unsigned)*s-0x80 >= 0x40) goto ilseq;
+                       c = (c<<6) | *s++-0x80;
+                       if (!(c&(1U<<31))) break;
+
+                       if ((unsigned)*s-0x80 >= 0x40) goto ilseq;
+                       c = (c<<6) | *s++-0x80;
+                       if (!(c&(1U<<31))) break;
+#endif
+
+                       if ((unsigned)*s-0x80 >= 0x40) goto ilseq;
+                       c = (c<<6) | *s++-0x80;
+                       if (!(c&(1U<<31))) break;
+
+                       if ((unsigned)*s-0x80 >= 0x40) goto ilseq;
+                       c = (c<<6) | *s++-0x80;
+               } while (0);
+
+               *ws++ = c; wn--; c = 0;
+       }
+       *src = s;
+       return ws-wsorig;
+ilseq:
+       *src = s;
+ilseq2:
+       /* enter permanently failing state */
+       *(unsigned *)st = FAILSTATE;
+       errno = EILSEQ;
+       return -1;
+}
diff --git a/src/multibyte/mbstowcs.c b/src/multibyte/mbstowcs.c
new file mode 100644 (file)
index 0000000..23e1d92
--- /dev/null
@@ -0,0 +1,18 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t mbstowcs(wchar_t *ws, const char *s, size_t wn)
+{
+       mbstate_t st = { 0 };
+       return mbsrtowcs(ws, (void*)&s, wn, &st);
+}
diff --git a/src/multibyte/mbtowc.c b/src/multibyte/mbtowc.c
new file mode 100644 (file)
index 0000000..bdcaeb3
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+int mbtowc(wchar_t *wc, const char *s, size_t n)
+{
+       mbstate_t st = { 0 };
+       n = mbrtowc(wc, s, n, &st);
+       return n+2 ? n : -1;
+}
diff --git a/src/multibyte/wcrtomb.c b/src/multibyte/wcrtomb.c
new file mode 100644 (file)
index 0000000..36180c8
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t wcrtomb(char *s, wchar_t wc, mbstate_t *st)
+{
+       if (!s) return 1;
+       if ((unsigned)wc < 0x80) {
+               *s = wc;
+               return 1;
+       } else if ((unsigned)wc < 0x800) {
+               *s++ = 0xc0 | (wc>>6);
+               *s = 0x80 | (wc&0x3f);
+               return 2;
+       } else if ((unsigned)wc < 0xd800 || (unsigned)wc-0xe000 < 0x2000) {
+               *s++ = 0xe0 | (wc>>12);
+               *s++ = 0x80 | ((wc>>6)&0x3f);
+               *s = 0x80 | (wc&0x3f);
+               return 3;
+       } else if ((unsigned)wc-0x10000 < 0x100000) {
+               *s++ = 0xf0 | (wc>>18);
+               *s++ = 0x80 | ((wc>>12)&0x3f);
+               *s++ = 0x80 | ((wc>>6)&0x3f);
+               *s = 0x80 | (wc&0x3f);
+               return 4;
+       }
+       errno = EILSEQ;
+       return -1;
+}
diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c
new file mode 100644 (file)
index 0000000..666f6f3
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t wcsnrtombs(char *dst, const wchar_t **wcs, size_t wn, size_t n, mbstate_t *st)
+{
+       size_t l, cnt=0, n2;
+       char *s, buf[256];
+       const wchar_t *ws = *wcs;
+
+       if (!dst) s = buf, n = sizeof buf;
+       else s = dst;
+
+       while ( n && ( (n2=wn)>=n || n2>32 ) ) {
+               if (n2>=n) n2=n;
+               wn -= n2;
+               l = wcsrtombs(s, &ws, n2, 0);
+               if (!(l+1)) {
+                       cnt = l;
+                       n = 0;
+                       break;
+               }
+               if (s != buf) {
+                       s += l;
+                       n -= l;
+               }
+               cnt += l;
+       }
+       while (n && wn) {
+               l = wcrtomb(s, *ws, 0);
+               if (!(l+1)) {
+                       cnt = l;
+                       break;
+               }
+               ws++; wn--;
+               /* safe - this loop runs fewer than sizeof(buf) times */
+               s+=l; n-=l;
+               cnt++;
+       }
+       if (dst) *wcs = ws;
+       return cnt;
+}
diff --git a/src/multibyte/wcsrtombs.c b/src/multibyte/wcsrtombs.c
new file mode 100644 (file)
index 0000000..3c48d65
--- /dev/null
@@ -0,0 +1,58 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t wcsrtombs(char *s, const wchar_t **ws, size_t n, mbstate_t *st)
+{
+       const wchar_t *ws2;
+       char buf[4];
+       size_t N = n, l;
+       if (!s) {
+               for (n=0, ws2=*ws; *ws2; ws2++) {
+                       if (*ws2 >= 0x80) {
+                               l = wcrtomb(buf, *ws2, 0);
+                               if (!(l+1)) return -1;
+                               n += l;
+                       } else n++;
+               }
+               return n;
+       }
+       while (n>=4 && **ws) {
+               if (**ws >= 0x80) {
+                       l = wcrtomb(s, **ws, 0);
+                       if (!(l+1)) return -1;
+                       s += l;
+                       n -= l;
+               } else {
+                       *s++ = **ws;
+                       n--;
+               }
+               (*ws)++;
+       }
+       while (n && **ws) {
+               if (**ws >= 0x80) {
+                       l = wcrtomb(buf, **ws, 0);
+                       if (!(l+1)) return -1;
+                       if (l>n) return N-n;
+                       wcrtomb(s, **ws, 0);
+                       s += l;
+                       n -= l;
+               } else {
+                       *s++ = **ws;
+                       n--;
+               }
+               (*ws)++;
+       }
+       if (n) *s = 0;
+       *ws = 0;
+       return N-n;
+}
diff --git a/src/multibyte/wcstombs.c b/src/multibyte/wcstombs.c
new file mode 100644 (file)
index 0000000..b9c1b18
--- /dev/null
@@ -0,0 +1,17 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+size_t wcstombs(char *s, const wchar_t *ws, size_t n)
+{
+       return wcsrtombs(s, &ws, n, 0);
+}
diff --git a/src/multibyte/wctob.c b/src/multibyte/wctob.c
new file mode 100644 (file)
index 0000000..d6353ee
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <wchar.h>
+
+int wctob(wint_t c)
+{
+       if (c < 128U) return c;
+       return EOF;
+}
diff --git a/src/multibyte/wctomb.c b/src/multibyte/wctomb.c
new file mode 100644 (file)
index 0000000..6910ef3
--- /dev/null
@@ -0,0 +1,18 @@
+/* 
+ * This code was written by Rich Felker in 2010; no copyright is claimed.
+ * This code is in the public domain. Attribution is appreciated but
+ * unnecessary.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <wchar.h>
+#include <errno.h>
+
+#include "internal.h"
+
+int wctomb(char *s, wchar_t wc)
+{
+       if (!s) return 0;
+       return wcrtomb(s, wc, 0);
+}
diff --git a/src/network/__dns.c b/src/network/__dns.c
new file mode 100644 (file)
index 0000000..73ec422
--- /dev/null
@@ -0,0 +1,267 @@
+#include <stdint.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <time.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "__dns.h"
+#include "stdio_impl.h"
+
+#define TIMEOUT 5
+#define RETRY 1
+#define PACKET_MAX 512
+#define PTR_MAX (64 + sizeof ".in-addr.arpa")
+
+int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt)
+{
+       time_t t0 = time(0);
+       int fd;
+       FILE *f, _f;
+       unsigned char _buf[64];
+       char line[64], *s, *z;
+       union {
+               struct sockaddr_in sin;
+               struct sockaddr_in6 sin6;
+       } sa = {0}, ns[3] = {{0}};
+       socklen_t sl;
+       int nns;
+       int family;
+       unsigned char q[280] = "", *r = dest;
+       int ql;
+       int rlen;
+       int got = 0, failed = 0;
+       int errcode = EAI_AGAIN;
+       int i, j;
+       struct timeval tv;
+       fd_set fds;
+       int id;
+
+       /* Construct query template - RR and ID will be filled later */
+       if (strlen(name)-1 >= 254U) return -1;
+       q[2] = q[5] = 1;
+       strcpy(q+13, name);
+       for (i=13; q[i]; i=j+1) {
+               for (j=i; q[j] && q[j] != '.'; j++);
+               if (j-i-1u > 62u) return -1;
+               q[i-1] = j-i;
+       }
+       q[i+3] = 1;
+       ql = i+4;
+
+       /* Make a reasonably unpredictable id */
+       gettimeofday(&tv, 0);
+       id = tv.tv_usec + tv.tv_usec/256 & 0xffff;
+
+       /* Get nameservers from resolv.conf, fallback to localhost */
+       f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf);
+       if (f) for (nns=0; nns<3 && fgets(line, sizeof line, f); ) {
+               if (strncmp(line, "nameserver", 10) || !isspace(line[10]))
+                       continue;
+               for (s=line+11; isspace(*s); s++);
+               for (z=s; *z && !isspace(*z); z++);
+               *z=0;
+               if (__ipparse(ns+nns, family, s) < 0) continue;
+               ns[nns].sin.sin_port = htons(53);
+               family = ns[nns++].sin.sin_family;
+               sl = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
+       }
+       if (f) __fclose_ca(f);
+       if (!nns) {
+               ns[0].sin.sin_family = AF_INET;
+               ns[0].sin.sin_port = htons(53);
+               nns=1;
+               sl = sizeof sa.sin;
+       }
+
+       /* Get local address and open/bind a socket */
+       sa.sin.sin_family = family;
+       fd = socket(family, SOCK_DGRAM, 0);
+       if (bind(fd, (void *)&sa, sl) < 0) {
+               close(fd);
+               return -1;
+       }
+       /* Nonblocking to work around Linux UDP select bug */
+       fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+
+       /* Loop until we timeout; break early on success */
+       for (; time(0)-t0 < TIMEOUT; ) {
+
+               /* Query all configured namservers in parallel */
+               for (i=0; i<rrcnt; i++) if (rr[i]) for (j=0; j<nns; j++) {
+                       q[0] = id+i >> 8;
+                       q[1] = id+i;
+                       q[ql-3] = rr[i];
+                       sendto(fd, q, ql, MSG_NOSIGNAL, (void *)&ns[j], sl);
+               }
+
+               /* Wait for a response, or until time to retry */
+               FD_ZERO(&fds);
+               FD_SET(fd, &fds);
+               tv.tv_sec = RETRY;
+               tv.tv_usec = 0;
+               if (select(fd+1, &fds, 0, 0, &tv) <= 0) continue;
+
+               /* Process any and all replies */
+               while (got+failed < rrcnt && (rlen = recvfrom(fd, r, 512, 0,
+                       (void *)&sa, (socklen_t[1]){sl})) >= 2)
+               {
+                       /* Ignore replies from addresses we didn't send to */
+                       for (i=0; i<nns; i++) if (!memcmp(ns+i, &sa, sl)) break;
+                       if (i==nns) continue;
+
+                       /* Compute index of the query from id */
+                       i = r[0]*256+r[1] - id & 0xffff;
+                       if ((unsigned)i >= rrcnt || !rr[i]) continue;
+
+                       /* Interpret the result code */
+                       switch (r[3] & 15) {
+                       case 0:
+                               got++;
+                               break;
+                       case 3:
+                               if (1) errcode = EAI_NONAME; else
+                       default:
+                               errcode = EAI_FAIL;
+                               failed++;
+                       }
+
+                       /* Mark this record as answered */
+                       rr[i] = 0;
+                       r += 512;
+               }
+
+               /* Check to see if we have answers to all queries */
+               if (got+failed == rrcnt) break;
+       }
+       close(fd);
+
+       /* Return the number of results, or an error code if none */
+       if (got) return got;
+       return errcode;
+}
+
+static void mkptr4(char *s, const unsigned char *ip)
+{
+       sprintf(s, "%d.%d.%d.%d.in-addr.arpa",
+               ip[3], ip[2], ip[1], ip[0]);
+}
+
+static void mkptr6(char *s, const unsigned char *ip)
+{
+       static const char xdigits[] = "0123456789abcdef";
+       int i;
+       for (i=15; i>=0; i--) {
+               *s++ = xdigits[ip[i]&15]; *s++ = '.';
+               *s++ = xdigits[ip[i]>>4]; *s++ = '.';
+       }
+       strcpy(s, "ip6.arpa");
+}
+
+int __dns_query(unsigned char *r, const void *a, int family, int ptr)
+{
+       char buf[PTR_MAX];
+       int rr[2], rrcnt = 1;
+
+       if (ptr) {
+               if (family == AF_INET6) mkptr6(buf, a);
+               else mkptr4(buf, a);
+               rr[0] = RR_PTR;
+               a = buf;
+       } else if (family == AF_INET6) {
+               rr[0] = RR_AAAA;
+       } else {
+               rr[0] = RR_A;
+               if (family != AF_INET) rr[rrcnt++] = RR_AAAA;
+       }
+
+       return __dns_doqueries(r, a, rr, rrcnt);
+}
+
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+static int decname(char *s, const unsigned char *b, const unsigned char *p)
+{
+       /* Remember jump destinations to detect loops and abort */
+       size_t seen[PACKET_MAX/8/sizeof(size_t)] = { 0 };
+       char *sz = s + HOST_NAME_MAX;
+       const unsigned char *pz = b+512;
+       for (;;) {
+               if (p>=pz) return -1;
+               else if (*p&0xc0) {
+                       int j = (p[0]&1) | p[1];
+                       if (BITOP(seen, j, &)) return -1;
+                       BITOP(seen, j, |=);
+                       p = b + j;
+               } else if (*p) {
+                       if (p+*p+1>=pz || s+*p>=sz) return -1;
+                       memcpy(s, p+1, *p);
+                       s += *p+1;
+                       p += *p+1;
+                       s[-1] = *p ? '.' : 0;
+               } else return 0;
+       }
+}
+
+int __dns_get_rr(void *dest, size_t stride, size_t maxlen, size_t limit, const unsigned char *r, int rr, int dec)
+{
+       int qdcount, ancount;
+       const unsigned char *p;
+       char tmp[256];
+       int found = 0;
+       int len;
+
+       if ((r[3]&15)) return 0;
+       p = r+12;
+       qdcount = r[4]*256 + r[5];
+       ancount = r[6]*256 + r[7];
+       if (qdcount+ancount > 64) return -1;
+       while (qdcount--) {
+               while (p-r < 512 && *p-1U < 127) p++;
+               if (*p>193 || (*p==193 && p[1]>254) || p>r+506)
+                       return -1;
+               p += 5 + !!*p;
+       }
+       while (ancount--) {
+               while (p-r < 512 && *p-1U < 127) p++;
+               if (*p>193 || (*p==193 && p[1]>254) || p>r+506)
+                       return -1;
+               p += 1 + !!*p;
+               len = p[8]*256 + p[9];
+               if (p+len > r+512) return -1;
+               if (p[1]==rr && len <= maxlen) {
+                       if (dec && decname(tmp, r, p+10)<0) return -1;
+                       if (dest && limit) {
+                               if (dec) strcpy(dest, tmp);
+                               else memcpy(dest, p+10, len);
+                               dest = (char *)dest + stride;
+                               limit--;
+                       }
+                       found++;
+               }
+               p += 10 + len;
+       }
+       return found;
+}
+
+int __dns_count_addrs(const unsigned char *r, int cnt)
+{
+       int found=0, res, i;
+       static const int p[2][2] = { { 4, RR_A }, { 16, RR_AAAA } };
+
+       while (cnt--) for (i=0; i<2; i++) {
+               res = __dns_get_rr(0, 0, p[i][0], -1, r, p[i][1], 0);
+               if (res < 0) return res;
+               found += res;
+               r += 512;
+       }
+       return found;
+}
diff --git a/src/network/__dns.h b/src/network/__dns.h
new file mode 100644 (file)
index 0000000..9a3f740
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stddef.h>
+
+#define RR_A 1
+#define RR_CNAME 5
+#define RR_PTR 12
+#define RR_AAAA 28
+
+int __dns_count_addrs(const unsigned char *, int);
+int __dns_get_rr(void *, size_t, size_t, size_t, const unsigned char *, int, int);
+
+int __dns_query(unsigned char *, const void *, int, int);
+int __ipparse(void *, int, const char *);
+
+int __dns_doqueries(unsigned char *, const char *, int *, int);
diff --git a/src/network/__ipparse.c b/src/network/__ipparse.c
new file mode 100644 (file)
index 0000000..ca9e589
--- /dev/null
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "__dns.h"
+#include <stdio.h>
+
+int __ipparse(void *dest, int family, const char *s)
+{
+       unsigned char *d = dest;
+       unsigned long a[16] = { 0 };
+       const char *z;
+       int i;
+
+       if (family == AF_INET6) goto not_v4;
+
+       for (i=0; i<4 && *s; i++) {
+               a[i] = strtoul(s, (char **)&z, 0);
+               if (z==s || (*z && *z != '.')) goto not_v4;
+               s=z+1;
+       }
+       switch (i) {
+       case 0:
+               a[1] = a[0] & 0xffffff;
+               a[0] >>= 24;
+       case 1:
+               a[2] = a[1] & 0xffff;
+               a[1] >>= 16;
+       case 2:
+               a[3] = a[2] & 0xff;
+               a[2] >>= 8;
+       }
+       ((struct sockaddr_in *)d)->sin_family = AF_INET;
+       d = (void *)&((struct sockaddr_in *)d)->sin_addr;
+       for (i=0; i<4; i++) d[i] = a[i];
+       return 0;
+
+not_v4:
+       return -1;
+}
diff --git a/src/network/accept.c b/src/network/accept.c
new file mode 100644 (file)
index 0000000..8370409
--- /dev/null
@@ -0,0 +1,14 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+int accept(int fd, struct sockaddr *addr, socklen_t *len)
+{
+       unsigned long args[] = { fd, (unsigned long)addr, (unsigned long)len };
+       int ret;
+       CANCELPT_BEGIN;
+       ret = syscall2(__NR_socketcall, SYS_ACCEPT, (long)args);
+       CANCELPT_END;
+       return ret;
+}
diff --git a/src/network/bind.c b/src/network/bind.c
new file mode 100644 (file)
index 0000000..3bef382
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int bind(int fd, const struct sockaddr *addr, socklen_t len)
+{
+       unsigned long args[] = { fd, (unsigned long)addr, len };
+       return syscall2(__NR_socketcall, SYS_BIND, (long)args);
+}
diff --git a/src/network/connect.c b/src/network/connect.c
new file mode 100644 (file)
index 0000000..6074122
--- /dev/null
@@ -0,0 +1,14 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+int connect(int fd, const struct sockaddr *addr, socklen_t len)
+{
+       unsigned long args[] = { fd, (unsigned long)addr, len };
+       int ret;
+       CANCELPT_BEGIN;
+       ret = syscall2(__NR_socketcall, SYS_CONNECT, (long)args);
+       CANCELPT_END;
+       return ret;
+}
diff --git a/src/network/dn_expand.c b/src/network/dn_expand.c
new file mode 100644 (file)
index 0000000..01b449b
--- /dev/null
@@ -0,0 +1,28 @@
+#include <resolv.h>
+#include <string.h>
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+int dn_expand(unsigned char *b, unsigned char *pz, unsigned char *p, unsigned char *s, int outlen)
+{
+       /* Remember jump destinations to detect loops and abort */
+       size_t seen[512/8/sizeof(size_t)] = { 0 };
+       unsigned char *sz = s + outlen;
+       if (pz-b > 512) return -1;
+       for (;;) {
+               if (p>=pz) return -1;
+               else if (*p&0xc0) {
+                       int j = (p[0]&1) | p[1];
+                       if (BITOP(seen, j, &)) return -1;
+                       BITOP(seen, j, |=);
+                       p = b + j;
+               } else if (*p) {
+                       if (p+*p+1>=pz || s+*p>=sz) return -1;
+                       memcpy(s, p+1, *p);
+                       s += *p+1;
+                       p += *p+1;
+                       s[-1] = *p ? '.' : 0;
+               } else return 0;
+       }
+}
diff --git a/src/network/ent.c b/src/network/ent.c
new file mode 100644 (file)
index 0000000..4c2f24b
--- /dev/null
@@ -0,0 +1,26 @@
+#include "libc.h"
+
+void sethostent(int x)
+{
+}
+
+void *gethostent()
+{
+       return 0;
+}
+
+void endhostent(void)
+{
+}
+
+weak_alias(sethostent, setnetent);
+weak_alias(gethostent, getnetent);
+weak_alias(endhostent, endnetent);
+
+weak_alias(sethostent, setservent);
+weak_alias(gethostent, getservent);
+weak_alias(endhostent, endservent);
+
+weak_alias(sethostent, setprotoent);
+weak_alias(gethostent, getprotoent);
+weak_alias(endhostent, endprotoent);
diff --git a/src/network/freeaddrinfo.c b/src/network/freeaddrinfo.c
new file mode 100644 (file)
index 0000000..df3798a
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+#include <netdb.h>
+
+void freeaddrinfo(struct addrinfo *p)
+{
+       free(p);
+}
diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c
new file mode 100644 (file)
index 0000000..ea00bed
--- /dev/null
@@ -0,0 +1,21 @@
+#include <netdb.h>
+
+static const char msgs[] =
+       "Invalid flags\0"
+       "Name does not resolve\0"
+       "Try again\0"
+       "Non-recoverable error\0"
+       "Unrecognized address family or invalid length\0"
+       "Unrecognized socket type\0"
+       "Unrecognized service\0"
+       "Out of memory\0"
+       "System error\0"
+       "Overflow\0"
+       "\0Unknown error";
+
+const char *gai_strerror(int ecode)
+{
+       const char *s;
+       for (s=msgs, ecode++; ecode && *s; ecode++, s++) for (; *s; s++);
+       return *s ? s : s+1;
+}
diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c
new file mode 100644 (file)
index 0000000..90e85f6
--- /dev/null
@@ -0,0 +1,224 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include "__dns.h"
+#include "stdio_impl.h"
+
+static int is_valid(const char *host)
+{
+       const unsigned char *s;
+       if (strlen(host)-1 > 254 || mbstowcs(0, host, 0) > 255) return 0;
+       for (s=host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++);
+       return !*s;
+}
+
+#if 0
+static int have_af(int family)
+{
+       struct sockaddr_in6 sin6 = { .sin6_family = family };
+       socklen_t sl = family == AF_INET
+               ? sizeof(struct sockaddr_in)
+               : sizeof(struct sockaddr_in6);
+       int sock = socket(family, SOCK_STREAM, 0);
+       int have = !bind(sock, (void *)&sin6, sl);
+       close(sock);
+       return have;
+}
+#endif
+
+#include <stdlib.h>
+#include <netdb.h>
+
+union sa {
+       struct sockaddr_in sin;
+       struct sockaddr_in6 sin6;
+};
+
+struct aibuf {
+       struct addrinfo ai;
+       union sa sa;
+};
+
+/* Extra slots needed for storing canonical name */
+#define EXTRA ((256+sizeof(struct aibuf)-1)/sizeof(struct aibuf))
+
+int getaddrinfo(const char *host, const char *serv, const struct addrinfo *hint, struct addrinfo **res)
+{
+       int flags = hint ? hint->ai_flags : 0;
+       int family = hint ? hint->ai_family : AF_UNSPEC;
+       int type = hint ? hint->ai_socktype : 0;
+       int proto = hint ? hint->ai_protocol : 0;
+       unsigned long port = 0;
+       struct aibuf *buf;
+       union sa sa = {{0}};
+       unsigned char reply[1024];
+       int i, j;
+       //char hostbuf[256];
+       char line[512];
+       FILE *f, _f;
+       unsigned char _buf[64];
+       char *z;
+       int result;
+       int cnt;
+
+       if (host && strlen(host)>255) return EAI_NONAME;
+       if (serv && strlen(serv)>32) return EAI_SERVICE;
+
+       if (type && !proto)
+               proto = type==SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
+       if (!type && proto)
+               type = proto==IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+
+       if (serv) {
+               port = strtoul(serv, &z, 0);
+               if (!*z && port > 65535) return EAI_SERVICE;
+               if (!port) {
+                       if (flags & AI_NUMERICSERV) return EAI_SERVICE;
+
+                       //f = fopen("/etc/services", "rb");
+                       return EAI_SERVICE;
+               }
+               port = htons(port);
+       }
+
+       if (!host) {
+               if (family == AF_UNSPEC) family = AF_INET;
+               buf = calloc(sizeof *buf, 1+EXTRA);
+               if (!buf) return EAI_MEMORY;
+               buf->ai.ai_protocol = proto;
+               buf->ai.ai_socktype = type;
+               buf->ai.ai_addr = (void *)&buf->sa;
+               buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
+               buf->ai.ai_family = family;
+               buf->sa.sin.sin_family = family;
+               buf->sa.sin.sin_port = port;
+               if (!(flags & AI_PASSIVE)) {
+                       if (family == AF_INET) {
+                               0[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=127;
+                               3[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=1;
+                       } else buf[0].sa.sin6.sin6_addr.s6_addr[15] = 1;
+               }
+               *res = &buf->ai;
+               return 0;
+       }
+
+       /* Try as a numeric address */
+       if (__ipparse(&sa, family, host) >= 0) {
+               buf = calloc(sizeof *buf, 1+EXTRA);
+               if (!buf) return EAI_MEMORY;
+               family = sa.sin.sin_family;
+               buf->ai.ai_protocol = proto;
+               buf->ai.ai_socktype = type;
+               buf->ai.ai_addr = (void *)&buf->sa;
+               buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
+               buf->ai.ai_family = family;
+               buf->sa = sa;
+               buf->sa.sin.sin_port = port;
+               *res = &buf->ai;
+               return 0;
+       }
+
+       if (flags & AI_NUMERICHOST) return EAI_NONAME;
+
+       f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
+       if (f) while (fgets(line, sizeof line, f)) {
+               char *p;
+               size_t l = strlen(host);
+
+               if ((p=strchr(line, '#'))) *p++='\n', *p=0;
+               for(p=line+1; (p=strstr(p, host)) &&
+                       (!isspace(p[-1]) || !isspace(p[l])); p++);
+               if (!p) continue;
+               __fclose_ca(f);
+
+               /* Isolate IP address to parse */
+               for (p=line; *p && !isspace(*p); p++);
+               *p++ = 0;
+               if (__ipparse(&sa, family, line) < 0) return EAI_NONAME;
+
+               /* Allocate and fill result buffer */
+               buf = calloc(sizeof *buf, 1+EXTRA);
+               if (!buf) return EAI_MEMORY;
+               family = sa.sin.sin_family;
+               buf->ai.ai_protocol = proto;
+               buf->ai.ai_socktype = type;
+               buf->ai.ai_addr = (void *)&buf->sa;
+               buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
+               buf->ai.ai_family = family;
+               buf->sa = sa;
+               buf->sa.sin.sin_port = port;
+
+               /* Extract first name as canonical name */
+               for (; *p && isspace(*p); p++);
+               buf->ai.ai_canonname = (void *)(buf+1);
+               snprintf(buf->ai.ai_canonname, 256, "%s", p);
+               for (p=buf->ai.ai_canonname; *p && !isspace(*p); p++);
+               *p = 0;
+               if (!is_valid(buf->ai.ai_canonname))
+                       buf->ai.ai_canonname = 0;
+
+               *res = &buf->ai;
+               return 0;
+       }
+       if (f) __fclose_ca(f);
+
+#if 0
+       f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf);
+       if (f) while (fgets(line, sizeof line, f)) {
+               if (!isspace(line[10]) || (strncmp(line, "search", 6)
+                       && strncmp(line, "domain", 6))) continue;
+       }
+       if (f) __fclose_ca(f);
+#endif
+
+       /* Perform one or more DNS queries for host */
+       memset(reply, 0, sizeof reply);
+       result = __dns_query(reply, host, family, 0);
+       if (result < 0) return result;
+
+       cnt = __dns_count_addrs(reply, result);
+       if (cnt <= 0) return EAI_NONAME;
+
+       buf = calloc(sizeof *buf, cnt+EXTRA);
+       if (!buf) return EAI_MEMORY;
+
+       i = 0;
+       if (family != AF_INET6) {
+               j = __dns_get_rr(&buf[i].sa.sin.sin_addr, sizeof *buf, 4, cnt-i, reply, RR_A, 0);
+               while (j--) buf[i++].sa.sin.sin_family = AF_INET;
+       }
+       if (family != AF_INET) {
+               j = __dns_get_rr(&buf[i].sa.sin6.sin6_addr, sizeof *buf, 16, cnt-i, reply, RR_AAAA, 0);
+               while (j--) buf[i++].sa.sin.sin_family = AF_INET6;
+       }
+       if (result>1) {
+               j = __dns_get_rr(&buf[i].sa.sin.sin_addr, sizeof *buf, 4, cnt-i, reply+512, RR_A, 0);
+               while (j--) buf[i++].sa.sin.sin_family = AF_INET;
+               j = __dns_get_rr(&buf[i].sa.sin6.sin6_addr, sizeof *buf, 16, cnt-i, reply+512, RR_AAAA, 0);
+               while (j--) buf[i++].sa.sin.sin_family = AF_INET6;
+       }
+
+       if (__dns_get_rr((void *)&buf[cnt], 0, 256, 1, reply, RR_CNAME, 1) < 0)
+               strcpy((void *)&buf[cnt], host);
+
+       for (i=0; i<cnt; i++) {
+               buf[i].ai.ai_protocol = proto;
+               buf[i].ai.ai_socktype = type;
+               buf[i].ai.ai_addr = (void *)&buf[i].sa;
+               buf[i].ai.ai_addrlen = buf[i].sa.sin.sin_family==AF_INET6
+                       ? sizeof sa.sin6 : sizeof sa.sin;
+               buf[i].ai.ai_family = buf[i].sa.sin.sin_family;
+               buf[i].sa.sin.sin_port = port;
+               buf[i].ai.ai_next = &buf[i+1].ai;
+               buf[i].ai.ai_canonname = (void *)&buf[cnt];
+       }
+       buf[cnt-1].ai.ai_next = 0;
+       *res = &buf->ai;
+
+       return 0;
+}
diff --git a/src/network/gethostbyaddr.c b/src/network/gethostbyaddr.c
new file mode 100644 (file)
index 0000000..51e1c56
--- /dev/null
@@ -0,0 +1,15 @@
+#define _GNU_SOURCE
+
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+
+struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
+{
+       static struct hostent h;
+       static long buf[512/sizeof(long)];
+       struct hostent *res;
+       if (gethostbyaddr_r(a, l, af, &h,
+               (void *)buf, sizeof buf, &res, &h_errno)) return 0;
+       return &h;
+}
diff --git a/src/network/gethostbyaddr_r.c b/src/network/gethostbyaddr_r.c
new file mode 100644 (file)
index 0000000..cdb1d50
--- /dev/null
@@ -0,0 +1,71 @@
+#define _GNU_SOURCE
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <inttypes.h>
+
+int gethostbyaddr_r(const void *a, socklen_t l, int af,
+       struct hostent *h, char *buf, size_t buflen,
+       struct hostent **res, int *err)
+{
+       union {
+               struct sockaddr_in sin;
+               struct sockaddr_in6 sin6;
+       } sa = { .sin.sin_family = af };
+       socklen_t sl = af==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
+       int i;
+
+       /* Load address argument into sockaddr structure */
+       if (af==AF_INET6 && l==16) memcpy(&sa.sin6.sin6_addr, a, 16);
+       else if (af==AF_INET && l==4) memcpy(&sa.sin.sin_addr, a, 4);
+       else {
+               *err = NO_RECOVERY;
+               return -1;
+       }
+
+       /* Align buffer and check for space for pointers and ip address */
+       i = (uintptr_t)buf & sizeof(char *)-1;
+       if (!i) i = sizeof(char *);
+       if (buflen <= 5*sizeof(char *)-i + l) {
+               errno = ERANGE;
+               return -1;
+       }
+       buf += sizeof(char *)-i;
+       buflen -= 5*sizeof(char *)-i + l;
+
+       h->h_addr_list = (void *)buf;
+       buf += 2*sizeof(char *);
+       h->h_aliases = (void *)buf;
+       buf += 2*sizeof(char *);
+
+       h->h_addr_list[0] = buf;
+       memcpy(h->h_addr_list[0], a, l);
+       buf += l;
+       h->h_addr_list[1] = 0;
+       h->h_aliases[0] = buf;
+       h->h_aliases[1] = 0;
+
+       switch (getnameinfo((void *)&sa, sl, buf, buflen, 0, 0, 0)) {
+       case EAI_AGAIN:
+               *err = TRY_AGAIN;
+               return -1;
+       case EAI_OVERFLOW:
+               errno = ERANGE;
+       default:
+       case EAI_MEMORY:
+       case EAI_SYSTEM:
+       case EAI_FAIL:
+               *err = NO_RECOVERY;
+               return -1;
+       case 0:
+               break;
+       }
+
+       h->h_addrtype = af;
+       h->h_name = h->h_aliases[0];
+       *res = h;
+       return 0;
+}
diff --git a/src/network/gethostbyname.c b/src/network/gethostbyname.c
new file mode 100644 (file)
index 0000000..5088a51
--- /dev/null
@@ -0,0 +1,63 @@
+#define _GNU_SOURCE
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+
+struct hostent *gethostbyname(const char *name)
+{
+       return gethostbyname2(name, AF_INET);
+}
+
+#if 0
+struct hostent *gethostbyname(const char *name)
+{
+       static struct hostent h;
+       static char *h_aliases[3];
+       static char h_canon[256];
+       static char *h_addr_list[10];
+       static char h_addr_data[10][4];
+       static const struct addrinfo hint = {
+               .ai_family = AF_INET, .ai_flags = AI_CANONNAME
+       };
+       struct addrinfo *ai, *p;
+       int i;
+
+       switch (getaddrinfo(name, 0, &hint, &ai)) {
+       case EAI_NONAME:
+               h_errno = HOST_NOT_FOUND;
+               break;
+       case EAI_AGAIN:
+               h_errno = TRY_AGAIN;
+               break;
+       case EAI_FAIL:
+               h_errno = NO_RECOVERY;
+               break;
+       default:
+       case EAI_MEMORY:
+       case EAI_SYSTEM:
+               h_errno = NO_DATA;
+               break;
+       case 0:
+               break;
+       }
+
+       strcpy(h_canon, ai->ai_canonname);
+       h.h_name = h_canon;
+       h.h_aliases = h_aliases;
+       h.h_aliases[0] = h_canon;
+       h.h_aliases[1] = strcmp(h_canon, name) ? (char *)name : 0;
+       h.h_length = 4;
+       h.h_addr_list = h_addr_list;
+       for (i=0, p=ai; i<sizeof h_addr_data/4 && p; i++, p=p->ai_next) {
+               h.h_addr_list[i] = h_addr_data[i];
+               memcpy(h.h_addr_list[i],
+                       &((struct sockaddr_in *)p->ai_addr)->sin_addr, 4);
+       }
+       h.h_addr_list[i] = 0;
+       h.h_addrtype = AF_INET;
+       freeaddrinfo(ai);
+       return &h;
+}
+#endif
diff --git a/src/network/gethostbyname2.c b/src/network/gethostbyname2.c
new file mode 100644 (file)
index 0000000..9fbe264
--- /dev/null
@@ -0,0 +1,16 @@
+#define _GNU_SOURCE
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+
+struct hostent *gethostbyname2(const char *name, int af)
+{
+       static struct hostent h;
+       static long buf[512/sizeof(long)];
+       struct hostent *res;
+       if (gethostbyname2_r(name, af, &h,
+               (void *)buf, sizeof buf, &res, &h_errno)) return 0;
+       return &h;
+}
diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c
new file mode 100644 (file)
index 0000000..c2ed75b
--- /dev/null
@@ -0,0 +1,99 @@
+#define _GNU_SOURCE
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <inttypes.h>
+
+int gethostbyname2_r(const char *name, int af,
+       struct hostent *h, char *buf, size_t buflen,
+       struct hostent **res, int *err)
+{
+       struct addrinfo hint = {
+               .ai_family = af==AF_INET6 ? af : AF_INET,
+               .ai_flags = AI_CANONNAME
+       };
+       struct addrinfo *ai, *p;
+       int i;
+       size_t need;
+       const char *canon;
+
+       af = hint.ai_family;
+
+       /* Align buffer */
+       i = (uintptr_t)buf & sizeof(char *)-1;
+       if (i) {
+               if (buflen < sizeof(char *)-i) {
+                       errno = ERANGE;
+                       return -1;
+               }
+               buf += sizeof(char *)-i;
+               buflen -= sizeof(char *)-i;
+       }
+
+       getaddrinfo(name, 0, &hint, &ai);
+       switch (getaddrinfo(name, 0, &hint, &ai)) {
+       case EAI_NONAME:
+               *err = HOST_NOT_FOUND;
+               return -1;
+       case EAI_AGAIN:
+               *err = TRY_AGAIN;
+               return -1;
+       default:
+       case EAI_MEMORY:
+       case EAI_SYSTEM:
+       case EAI_FAIL:
+               *err = NO_RECOVERY;
+               return -1;
+       case 0:
+               break;
+       }
+
+       h->h_addrtype = af;
+       h->h_length = af==AF_INET6 ? 16 : 4;
+
+       canon = ai->ai_canonname ? ai->ai_canonname : name;
+       need = 4*sizeof(char *);
+       for (i=0, p=ai; p; i++, p=p->ai_next)
+               need += sizeof(char *) + h->h_length;
+       need += strlen(name)+1;
+       need += strlen(canon)+1;
+
+       if (need > buflen) {
+               freeaddrinfo(ai);
+               errno = ERANGE;
+               return -1;
+       }
+
+       h->h_aliases = (void *)buf;
+       buf += 3*sizeof(char *);
+       h->h_addr_list = (void *)buf;
+       buf += (i+1)*sizeof(char *);
+
+       h->h_name = h->h_aliases[0] = buf;
+       strcpy(h->h_name, canon);
+       buf += strlen(h->h_name)+1;
+
+       if (strcmp(h->h_name, name)) {
+               h->h_aliases[1] = buf;
+               strcpy(h->h_aliases[1], name);
+               buf += strlen(h->h_aliases[1])+1;
+       } else h->h_aliases[1] = 0;
+
+       h->h_aliases[2] = 0;
+
+       for (i=0, p=ai; p; i++, p=p->ai_next) {
+               h->h_addr_list[i] = (void *)buf;
+               buf += h->h_length;
+               memcpy(h->h_addr_list[i],
+                       &((struct sockaddr_in *)p->ai_addr)->sin_addr,
+                       h->h_length);
+       }
+       h->h_addr_list[i] = 0;
+
+       *res = h;
+       freeaddrinfo(ai);
+       return 0;
+}
diff --git a/src/network/gethostbyname_r.c b/src/network/gethostbyname_r.c
new file mode 100644 (file)
index 0000000..cd87254
--- /dev/null
@@ -0,0 +1,11 @@
+#define _GNU_SOURCE
+
+#include <sys/socket.h>
+#include <netdb.h>
+
+int gethostbyname_r(const char *name,
+       struct hostent *h, char *buf, size_t buflen,
+       struct hostent **res, int *err)
+{
+       return gethostbyname2_r(name, AF_INET, h, buf, buflen, res, err);
+}
diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c
new file mode 100644 (file)
index 0000000..0763ca8
--- /dev/null
@@ -0,0 +1,54 @@
+#include <netdb.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "__dns.h"
+
+int getnameinfo(const struct sockaddr *sa, socklen_t sl,
+       char *node, socklen_t nodelen,
+       char *serv, socklen_t servlen,
+       int flags)
+{
+       char buf[256];
+       unsigned char reply[512];
+       int af = sa->sa_family;
+       unsigned char *a;
+
+       switch (af) {
+       case AF_INET:
+               a = (void *)&((struct sockaddr_in *)sa)->sin_addr;
+               if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY;
+               break;
+       case AF_INET6:
+               a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr;
+               if (sl != sizeof(struct sockaddr_in6)) return EAI_FAMILY;
+               break;
+       default:
+               return EAI_FAMILY;
+       }
+
+       if (node && nodelen) {
+               if ((flags & NI_NUMERICHOST)
+                       || __dns_query(reply, a, af, 1) <= 0
+                       || __dns_get_rr(buf, 0, 256, 1, reply, RR_PTR, 1) <= 0)
+               {
+                       if (flags & NI_NAMEREQD) return EAI_NONAME;
+                       inet_ntop(af, a, buf, sizeof buf);
+               }
+               if (strlen(buf) >= nodelen) return EAI_OVERFLOW;
+               strcpy(node, buf);
+       }
+
+       if (serv && servlen) {
+               if (snprintf(buf, sizeof buf, "%d",
+                       ntohs(((struct sockaddr_in *)sa)->sin_port))>=servlen)
+                       return EAI_OVERFLOW;
+               strcpy(serv, buf);
+       }
+
+       return 0;
+}
diff --git a/src/network/getpeername.c b/src/network/getpeername.c
new file mode 100644 (file)
index 0000000..7ecbe37
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int getpeername(int fd, struct sockaddr *addr, socklen_t *len)
+{
+       unsigned long args[] = { fd, (unsigned long)addr, (unsigned long)len };
+       return syscall2(__NR_socketcall, SYS_GETPEERNAME, (long)args);
+}
diff --git a/src/network/getservbyname.c b/src/network/getservbyname.c
new file mode 100644 (file)
index 0000000..0b00ce1
--- /dev/null
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include <netdb.h>
+
+struct servent *getservbyname(const char *name, const char *prots)
+{
+       static struct servent se;
+       static long buf[32/sizeof(long)];
+       struct servent *res;
+       if (getservbyname_r(name, prots, &se, (void *)buf, sizeof buf, &res))
+               return 0;
+       return &se;
+}
diff --git a/src/network/getservbyname_r.c b/src/network/getservbyname_r.c
new file mode 100644 (file)
index 0000000..5c02515
--- /dev/null
@@ -0,0 +1,41 @@
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <string.h>
+
+int getservbyname_r(const char *name, const char *prots,
+       struct servent *se, char *buf, size_t buflen, struct servent **res)
+{
+       struct addrinfo *ai, hint = { .ai_family = AF_INET };
+       int i;
+
+       /* Align buffer */
+       i = (uintptr_t)buf & sizeof(char *)-1;
+       if (!i) i = sizeof(char *);
+       if (buflen < 3*sizeof(char *)-i) {
+               errno = ERANGE;
+               return -1;
+       }
+       buf += sizeof(char *)-i;
+       buflen -= sizeof(char *)-i;
+
+       if (!strcmp(prots, "tcp")) hint.ai_protocol = IPPROTO_TCP;
+       else if (!strcmp(prots, "udp")) hint.ai_protocol = IPPROTO_UDP;
+       else return -1;
+
+       if (getaddrinfo(0, name, &hint, &ai) < 0) return -1;
+
+       se->s_name = (char *)name;
+       se->s_aliases = (void *)buf;
+       se->s_aliases[0] = se->s_name;
+       se->s_aliases[1] = 0;
+       se->s_port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
+       se->s_proto = (char *)prots;
+
+       freeaddrinfo(ai);
+       *res = se;
+       return 0;
+}
diff --git a/src/network/getservbyport.c b/src/network/getservbyport.c
new file mode 100644 (file)
index 0000000..c9ecbb1
--- /dev/null
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include <netdb.h>
+
+struct servent *getservbyport(int port, const char *prots)
+{
+       static struct servent se;
+       static long buf[32/sizeof(long)];
+       struct servent *res;
+       if (getservbyport_r(port, prots, &se, (void *)buf, sizeof buf, &res))
+               return 0;
+       return &se;
+}
diff --git a/src/network/getservbyport_r.c b/src/network/getservbyport_r.c
new file mode 100644 (file)
index 0000000..004a616
--- /dev/null
@@ -0,0 +1,43 @@
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <string.h>
+
+int getservbyport_r(int port, const char *prots,
+       struct servent *se, char *buf, size_t buflen, struct servent **res)
+{
+       int i;
+       struct sockaddr_in sin = {
+               .sin_family = AF_INET,
+               .sin_port = port,
+       };
+
+       /* Align buffer */
+       i = (uintptr_t)buf & sizeof(char *)-1;
+       if (!i) i = sizeof(char *);
+       if (buflen < 3*sizeof(char *)-i) {
+               errno = ERANGE;
+               return -1;
+       }
+       buf += sizeof(char *)-i;
+       buflen -= sizeof(char *)-i;
+
+       if (strcmp(prots, "tcp") && strcmp(prots, "udp")) return -1;
+
+       se->s_port = port;
+       se->s_proto = (char *)prots;
+       se->s_aliases = (void *)buf;
+       buf += 2*sizeof(char *);
+       buflen -= 2*sizeof(char *);
+       se->s_aliases[1] = 0;
+       se->s_aliases[0] = se->s_name = buf;
+
+       if (getnameinfo((void *)&sin, sizeof sin, 0, 0, buf, buflen, 
+               strcmp(prots, "udp") ? 0 : NI_DGRAM) < 0) return -1;
+
+       *res = se;
+       return 0;
+}
diff --git a/src/network/getsockname.c b/src/network/getsockname.c
new file mode 100644 (file)
index 0000000..4b1002f
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int getsockname(int fd, struct sockaddr *addr, socklen_t *len)
+{
+       unsigned long args[] = { fd, (unsigned long)addr, (unsigned long)len };
+       return syscall2(__NR_socketcall, SYS_GETSOCKNAME, (long)args);
+}
diff --git a/src/network/getsockopt.c b/src/network/getsockopt.c
new file mode 100644 (file)
index 0000000..8c81886
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen)
+{
+       unsigned long args[] = {
+               fd, level, optname,
+               (unsigned long)optval,
+               (unsigned long)optlen
+       };
+       return syscall2(__NR_socketcall, SYS_GETSOCKOPT, (long)args);
+}
diff --git a/src/network/h_errno.c b/src/network/h_errno.c
new file mode 100644 (file)
index 0000000..73ead04
--- /dev/null
@@ -0,0 +1 @@
+int h_errno;
diff --git a/src/network/hstrerror.c b/src/network/hstrerror.c
new file mode 100644 (file)
index 0000000..b7a6ab6
--- /dev/null
@@ -0,0 +1,16 @@
+#define _GNU_SOURCE
+#include <netdb.h>
+
+static const char msgs[] =
+       "Host not found\0"
+       "Try again\0"
+       "Non-recoverable error\0"
+       "Address not available\0"
+       "\0Unknown error";
+
+const char *hstrerror(int ecode)
+{
+       const char *s;
+       for (s=msgs, ecode--; ecode && *s; ecode--, s++) for (; *s; s++);
+       return *s ? s : s+1;
+}
diff --git a/src/network/htonl.c b/src/network/htonl.c
new file mode 100644 (file)
index 0000000..b21dace
--- /dev/null
@@ -0,0 +1,10 @@
+#include <netinet/in.h>
+
+uint32_t htonl(uint32_t n)
+{
+       union {
+               uint8_t b[4];
+               uint32_t i;
+       } u = { { n>>24, n>>16, n>>8, n } };
+       return u.i;
+}
diff --git a/src/network/htons.c b/src/network/htons.c
new file mode 100644 (file)
index 0000000..522504a
--- /dev/null
@@ -0,0 +1,10 @@
+#include <netinet/in.h>
+
+uint16_t htons(uint16_t n)
+{
+       union {
+               uint8_t b[2];
+               uint16_t s;
+       } u = { { n>>8, n } };
+       return u.s;
+}
diff --git a/src/network/in6addr_any.c b/src/network/in6addr_any.c
new file mode 100644 (file)
index 0000000..995387f
--- /dev/null
@@ -0,0 +1,3 @@
+#include <netinet/in.h>
+
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
diff --git a/src/network/in6addr_loopback.c b/src/network/in6addr_loopback.c
new file mode 100644 (file)
index 0000000..b96005b
--- /dev/null
@@ -0,0 +1,3 @@
+#include <netinet/in.h>
+
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
diff --git a/src/network/inet_addr.c b/src/network/inet_addr.c
new file mode 100644 (file)
index 0000000..8413728
--- /dev/null
@@ -0,0 +1,11 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "__dns.h"
+
+in_addr_t inet_addr(const char *p)
+{
+       struct sockaddr_in sin;
+       if (__ipparse(&sin, AF_INET, p)) return -1;
+       return sin.sin_addr.s_addr;
+}
diff --git a/src/network/inet_aton.c b/src/network/inet_aton.c
new file mode 100644 (file)
index 0000000..ea4ee16
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+int inet_aton(const char *cp, struct in_addr *inp)
+{
+       return inet_pton(AF_INET, cp, (void *)inp) > 0;
+}
diff --git a/src/network/inet_ntoa.c b/src/network/inet_ntoa.c
new file mode 100644 (file)
index 0000000..71411e0
--- /dev/null
@@ -0,0 +1,10 @@
+#include <arpa/inet.h>
+#include <stdio.h>
+
+char *inet_ntoa(struct in_addr in)
+{
+       static char buf[16];
+       unsigned char *a = (void *)&in;
+       snprintf(buf, sizeof buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
+       return buf;
+}
diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c
new file mode 100644 (file)
index 0000000..3e8a6db
--- /dev/null
@@ -0,0 +1,48 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+const char *inet_ntop(int af, const void *a0, char *s, socklen_t l)
+{
+       const unsigned char *a = a0;
+       int i, j, max, best;
+       char buf[100];
+
+       switch (af) {
+       case AF_INET:
+               if (snprintf(s, l, "%d.%d.%d.%d", a[0],a[1],a[2],a[3]) < l)
+                       return s;
+               break;
+       case AF_INET6:
+               memset(buf, 'x', sizeof buf);
+               buf[sizeof buf-1]=0;
+               snprintf(buf, sizeof buf, 
+                       "%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x",
+                       a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],
+                       a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15]);
+               /* Replace longest /(^0|:)[:0]{2,}/ with "::" */
+               for (i=best=0, max=2; buf[i]; i++) {
+                       if (i && buf[i] != ':') continue;
+                       j = strspn(buf+i, ":0");
+                       if (j>max) best=i, max=j;
+               }
+               if (max>2) {
+                       buf[best] = buf[best+1] = ':';
+                       strcpy(buf+best+2, buf+best+max);
+               }
+               if (strlen(buf) < l) {
+                       strcpy(s, buf);
+                       return s;
+               }
+               break;
+       default:
+               errno = EAFNOSUPPORT;
+               return 0;
+       }
+       errno = ENOSPC;
+       return 0;
+}
diff --git a/src/network/inet_pton.c b/src/network/inet_pton.c
new file mode 100644 (file)
index 0000000..349c402
--- /dev/null
@@ -0,0 +1,31 @@
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include "__dns.h"
+
+int inet_pton(int af, const char *s, void *a0)
+{
+       unsigned char *a = a0;
+       const char *z;
+       unsigned long x;
+       int i;
+
+       /* Reimplement this because inet_pton cannot accept special v4 forms */
+       if (af==AF_INET) {
+               for (i=0; i<4 && *s; i++) {
+                       a[i] = x = strtoul(s, (char **)&z, 10);
+                       if (!isdigit(*s) || z==s || (*z && *z != '.') || x>255)
+                               return 0;
+                       s=z+1;
+               }
+               return 0;
+       } else if (af==AF_INET6) {
+               return !__ipparse(a, AF_INET6, s);
+       }
+
+       errno = EAFNOSUPPORT;
+       return 0;
+}
diff --git a/src/network/listen.c b/src/network/listen.c
new file mode 100644 (file)
index 0000000..7c8c1a8
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int listen(int fd, int backlog)
+{
+       unsigned long args[] = { fd, backlog };
+       return syscall2(__NR_socketcall, SYS_LISTEN, (long)args);
+}
diff --git a/src/network/ntohl.c b/src/network/ntohl.c
new file mode 100644 (file)
index 0000000..6437919
--- /dev/null
@@ -0,0 +1,10 @@
+#include <netinet/in.h>
+
+uint32_t ntohl(uint32_t n)
+{
+       union {
+               uint32_t i;
+               uint8_t b[4];
+       } u = { n };
+       return (u.b[0]<<24) | (u.b[1]<<16) | (u.b[2]<<8) | u.b[3];
+}
diff --git a/src/network/ntohs.c b/src/network/ntohs.c
new file mode 100644 (file)
index 0000000..3544a47
--- /dev/null
@@ -0,0 +1,10 @@
+#include <netinet/in.h>
+
+uint16_t ntohs(uint16_t n)
+{
+       union {
+               uint16_t s;
+               uint8_t b[2];
+       } u = { n };
+       return (u.b[0]<<8) | u.b[1];
+}
diff --git a/src/network/proto.c b/src/network/proto.c
new file mode 100644 (file)
index 0000000..8c25c53
--- /dev/null
@@ -0,0 +1,58 @@
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+/* do we really need all these?? */
+
+static int idx;
+static const unsigned char protos[][6] = {
+       "\000ip",
+       "\001icmp",
+       "\002igmp",
+       "\003ggp",
+       "\006tcp",
+       "\014pup",
+       "\021udp",
+       "\026idp",
+       "\377raw"
+       "\0\0"
+};
+
+void endprotoent(void)
+{
+       idx = 0;
+}
+
+void setprotoent(int stayopen)
+{
+       idx = 0;
+}
+
+struct protoent *getprotoent(void)
+{
+       static struct protoent p;
+       static const char *aliases;
+       if (!protos[idx][1]) return NULL;
+       p.p_proto = protos[idx][0];
+       p.p_name = (char *)protos[idx++]+1;
+       p.p_aliases = (char **)&aliases;
+       return &p;
+}
+
+struct protoent *getprotobyname(const char *name)
+{
+       struct protoent *p;
+       endprotoent();
+       do p = getprotoent();
+       while (p && strcmp(name, p->p_name));
+       return p;
+}
+
+struct protoent *getprotobynumber(int num)
+{
+       struct protoent *p;
+       endprotoent();
+       do p = getprotoent();
+       while (p && p->p_proto != num);
+       return p;
+}
diff --git a/src/network/recv.c b/src/network/recv.c
new file mode 100644 (file)
index 0000000..521a4b1
--- /dev/null
@@ -0,0 +1,14 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+ssize_t recv(int fd, void *buf, size_t len, int flags)
+{
+       unsigned long args[] = { fd, (unsigned long)buf, len, flags };
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall2(__NR_socketcall, SYS_RECV, (long)args);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/network/recvfrom.c b/src/network/recvfrom.c
new file mode 100644 (file)
index 0000000..df50114
--- /dev/null
@@ -0,0 +1,17 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+ssize_t recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *alen)
+{
+       unsigned long args[] = {
+               fd, (unsigned long)buf, len, flags,
+               (unsigned long)addr, (unsigned long)alen
+       };
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall2(__NR_socketcall, SYS_RECVFROM, (long)args);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/network/recvmsg.c b/src/network/recvmsg.c
new file mode 100644 (file)
index 0000000..ead16f9
--- /dev/null
@@ -0,0 +1,14 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
+{
+       unsigned long args[] = { fd, (unsigned long)msg, flags };
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall2(__NR_socketcall, SYS_RECVMSG, (long)args);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/network/res_init.c b/src/network/res_init.c
new file mode 100644 (file)
index 0000000..cbd5b15
--- /dev/null
@@ -0,0 +1,4 @@
+int res_init()
+{
+       return 0;
+}
diff --git a/src/network/res_query.c b/src/network/res_query.c
new file mode 100644 (file)
index 0000000..4ebeb10
--- /dev/null
@@ -0,0 +1,20 @@
+#include <netdb.h>
+#include "__dns.h"
+
+int res_query(const char *name, int class, int type, unsigned char *dest, int len)
+{
+       if (class != 1 || len < 512)
+               return -1;
+       switch(__dns_doqueries(dest, name, &type, 1)) {
+       case EAI_NONAME:
+               h_errno = HOST_NOT_FOUND;
+               return -1;
+       case EAI_AGAIN:
+               h_errno = TRY_AGAIN;
+               return -1;
+       case EAI_FAIL:
+               h_errno = NO_RECOVERY;
+               return -1;
+       }
+       return 512;
+}
diff --git a/src/network/send.c b/src/network/send.c
new file mode 100644 (file)
index 0000000..d72fb03
--- /dev/null
@@ -0,0 +1,14 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+ssize_t send(int fd, const void *buf, size_t len, int flags)
+{
+       unsigned long args[] = { fd, (unsigned long)buf, len, flags };
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall2(__NR_socketcall, SYS_SEND, (long)args);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/network/sendmsg.c b/src/network/sendmsg.c
new file mode 100644 (file)
index 0000000..ea2fe48
--- /dev/null
@@ -0,0 +1,14 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+       unsigned long args[] = { fd, (unsigned long)msg, flags };
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall2(__NR_socketcall, SYS_SENDMSG, (long)args);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/network/sendto.c b/src/network/sendto.c
new file mode 100644 (file)
index 0000000..5d224b0
--- /dev/null
@@ -0,0 +1,17 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+#include "libc.h"
+
+ssize_t sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
+{
+       unsigned long args[] = {
+               fd, (unsigned long)buf, len, flags,
+               (unsigned long)addr, alen
+       };
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall2(__NR_socketcall, SYS_SENDTO, (long)args);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/network/serv.c b/src/network/serv.c
new file mode 100644 (file)
index 0000000..5ade6ad
--- /dev/null
@@ -0,0 +1,16 @@
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+void endservent(void)
+{
+}
+
+void setservent(int stayopen)
+{
+}
+
+struct servent *getservent(void)
+{
+       return 0;
+}
diff --git a/src/network/setsockopt.c b/src/network/setsockopt.c
new file mode 100644 (file)
index 0000000..b50303b
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
+{
+       unsigned long args[] = { fd, level, optname, (unsigned long)optval, optlen };
+       return syscall2(__NR_socketcall, SYS_SETSOCKOPT, (long)args);
+}
diff --git a/src/network/shutdown.c b/src/network/shutdown.c
new file mode 100644 (file)
index 0000000..91950c8
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int shutdown(int fd, int how)
+{
+       unsigned long args[] = { fd, how };
+       return syscall2(__NR_socketcall, SYS_SHUTDOWN, (long)args);
+}
diff --git a/src/network/sockatmark.c b/src/network/sockatmark.c
new file mode 100644 (file)
index 0000000..5328a85
--- /dev/null
@@ -0,0 +1,11 @@
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include "socketcall.h"
+
+int sockatmark(int s)
+{
+       int ret;
+       if (ioctl(s, SIOCATMARK, &ret) < 0)
+               return -1;
+       return ret;
+}
diff --git a/src/network/socket.c b/src/network/socket.c
new file mode 100644 (file)
index 0000000..afaeb41
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int socket(int domain, int type, int protocol)
+{
+       unsigned long args[] = { domain, type, protocol };
+       return syscall2(__NR_socketcall, SYS_SOCKET, (long)args);
+}
diff --git a/src/network/socketcall.h b/src/network/socketcall.h
new file mode 100644 (file)
index 0000000..9ae9858
--- /dev/null
@@ -0,0 +1,24 @@
+#define SYS_SOCKET      1
+#define SYS_BIND        2
+#define SYS_CONNECT     3
+#define SYS_LISTEN      4
+#define SYS_ACCEPT      5
+#define SYS_GETSOCKNAME 6
+#define SYS_GETPEERNAME 7
+#define SYS_SOCKETPAIR  8
+#define SYS_SEND        9
+#define SYS_RECV        10
+#define SYS_SENDTO      11
+#define SYS_RECVFROM    12
+#define SYS_SHUTDOWN    13
+#define SYS_SETSOCKOPT  14
+#define SYS_GETSOCKOPT  15
+#define SYS_SENDMSG     16
+#define SYS_RECVMSG     17
+
+#define FIOSETOWN       0x8901
+#define SIOCSPGRP       0x8902
+#define FIOGETOWN       0x8903
+#define SIOCGPGRP       0x8904
+#define SIOCATMARK      0x8905
+#define SIOCGSTAMP      0x8906
diff --git a/src/network/socketpair.c b/src/network/socketpair.c
new file mode 100644 (file)
index 0000000..65a47fd
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/socket.h>
+#include "syscall.h"
+#include "socketcall.h"
+
+int socketpair(int domain, int type, int protocol, int fd[2])
+{
+       unsigned long args[] = { domain, type, protocol, (unsigned long)fd };
+       return syscall2(__NR_socketcall, SYS_SOCKETPAIR, (long)args);
+}
diff --git a/src/passwd/getgr_r.c b/src/passwd/getgr_r.c
new file mode 100644 (file)
index 0000000..5b1333e
--- /dev/null
@@ -0,0 +1,53 @@
+#include "pwf.h"
+
+#define FIX(x) (gr->gr_##x = gr->gr_##x-line+buf)
+
+static int getgr_r(const char *name, gid_t gid, struct group *gr, char *buf, size_t size, struct group **res)
+{
+       FILE *f;
+       char *line = 0;
+       size_t len = 0;
+       char **mem = 0;
+       size_t nmem = 0;
+       int rv = 0;
+       size_t i;
+
+       f = fopen("/etc/group", "rb");
+       if (!f) return errno;
+
+       *res = 0;
+       while (__getgrent_a(f, gr, &line, &len, &mem, &nmem)) {
+               if (name && !strcmp(name, gr->gr_name)
+               || !name && gr->gr_gid == gid) {
+                       if (size < len + nmem*sizeof(char *) + 32) {
+                               rv = ERANGE;
+                               break;
+                       }
+                       *res = gr;
+                       buf += (16-(uintptr_t)buf)%16;
+                       gr->gr_mem = (void *)buf;
+                       buf += nmem*sizeof(char *);
+                       memcpy(buf, line, len);
+                       FIX(name);
+                       FIX(passwd);
+                       for (i=0; mem[i]; i++)
+                               gr->gr_mem[i] = mem[i]-line+buf;
+                       gr->gr_mem[i] = 0;
+                       break;
+               }
+       }
+       free(mem);
+       free(line);
+       fclose(f);
+       return rv;
+}
+
+int getgrnam_r(const char *name, struct group *gr, char *buf, size_t size, struct group **res)
+{
+       return getgr_r(name, 0, gr, buf, size, res);
+}
+
+int getgruid_r(gid_t gid, struct group *gr, char *buf, size_t size, struct group **res)
+{
+       return getgr_r(0, gid, gr, buf, size, res);
+}
diff --git a/src/passwd/getgrent.c b/src/passwd/getgrent.c
new file mode 100644 (file)
index 0000000..e9d25eb
--- /dev/null
@@ -0,0 +1,39 @@
+#include "pwf.h"
+
+static FILE *f;
+
+void setgrent()
+{
+       if (f) fclose(f);
+       f = 0;
+}
+
+weak_alias(setgrent, endgrent);
+
+struct group *getgrent()
+{
+       static char *line, **mem;
+       static struct group gr;
+       size_t size=0, nmem=0;
+       if (!f) f = fopen("/etc/group", "rb");
+       if (!f) return 0;
+       return __getgrent_a(f, &gr, &line, &size, &mem, &nmem);
+}
+
+struct group *getgrgid(gid_t gid)
+{
+       struct group *gr;
+       setgrent();
+       while ((gr=getgrent()) && gr->gr_gid != gid);
+       endgrent();
+       return gr;
+}
+
+struct group *getgrnam(const char *name)
+{
+       struct group *gr;
+       setgrent();
+       while ((gr=getgrent()) && strcmp(gr->gr_name, name));
+       endgrent();
+       return gr;
+}
diff --git a/src/passwd/getgrent_a.c b/src/passwd/getgrent_a.c
new file mode 100644 (file)
index 0000000..ccb51d5
--- /dev/null
@@ -0,0 +1,46 @@
+#include "pwf.h"
+
+struct group *__getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem)
+{
+       ssize_t l;
+       char *s, *mems;
+       size_t i;
+
+       for (;;) {
+               if ((l=getline(line, size, f)) < 0) {
+                       free(*line);
+                       *line = 0;
+                       return 0;
+               }
+               line[0][l-1] = 0;
+
+               s = line[0];
+               gr->gr_name = s++;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; gr->gr_passwd = s;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; gr->gr_gid = atoi(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; mems = s;
+               break;
+       }
+
+       for (*nmem=!!*s; *s; s++)
+               if (*s==',') ++*nmem;
+       free(*mem);
+       *mem = calloc(sizeof(char *), *nmem+1);
+       if (!*mem) {
+               free(*line);
+               *line = 0;
+               return 0;
+       }
+       mem[0][0] = mems;
+       for (s=mems, i=0; *s; s++)
+               if (*s==',') *s++ = 0, mem[0][++i] = s;
+       mem[0][++i] = 0;
+       gr->gr_mem = *mem;
+       return gr;
+}
diff --git a/src/passwd/getpw_r.c b/src/passwd/getpw_r.c
new file mode 100644 (file)
index 0000000..7b331e8
--- /dev/null
@@ -0,0 +1,46 @@
+#include "pwf.h"
+
+#define FIX(x) (pw->pw_##x = pw->pw_##x-line+buf)
+
+static int getpw_r(const char *name, uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res)
+{
+       FILE *f;
+       char *line = 0;
+       size_t len = 0;
+       int rv = 0;
+
+       f = fopen("/etc/passwd", "rb");
+       if (!f) return errno;
+
+       *res = 0;
+       while (__getpwent_a(f, pw, &line, &len)) {
+               if (name && !strcmp(name, pw->pw_name)
+               || !name && pw->pw_uid == uid) {
+                       if (size < len) {
+                               rv = ERANGE;
+                               break;
+                       }
+                       *res = pw;
+                       memcpy(buf, line, len);
+                       FIX(name);
+                       FIX(passwd);
+                       FIX(gecos);
+                       FIX(dir);
+                       FIX(shell);
+                       break;
+               }
+       }
+       free(line);
+       fclose(f);
+       return rv;
+}
+
+int getpwnam_r(const char *name, struct passwd *pw, char *buf, size_t size, struct passwd **res)
+{
+       return getpw_r(name, 0, pw, buf, size, res);
+}
+
+int getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res)
+{
+       return getpw_r(0, uid, pw, buf, size, res);
+}
diff --git a/src/passwd/getpwent.c b/src/passwd/getpwent.c
new file mode 100644 (file)
index 0000000..dabd411
--- /dev/null
@@ -0,0 +1,39 @@
+#include "pwf.h"
+
+static FILE *f;
+
+void setpwent()
+{
+       if (f) fclose(f);
+       f = 0;
+}
+
+weak_alias(setpwent, endpwent);
+
+struct passwd *getpwent()
+{
+       static char *line;
+       static struct passwd pw;
+       size_t size=0;
+       if (!f) f = fopen("/etc/passwd", "rb");
+       if (!f) return 0;
+       return __getpwent_a(f, &pw, &line, &size);
+}
+
+struct passwd *getpwuid(uid_t uid)
+{
+       struct passwd *pw;
+       setpwent();
+       while ((pw=getpwent()) && pw->pw_uid != uid);
+       endpwent();
+       return pw;
+}
+
+struct passwd *getpwnam(const char *name)
+{
+       struct passwd *pw;
+       setpwent();
+       while ((pw=getpwent()) && strcmp(pw->pw_name, name));
+       endpwent();
+       return pw;
+}
diff --git a/src/passwd/getpwent_a.c b/src/passwd/getpwent_a.c
new file mode 100644 (file)
index 0000000..aaf84ed
--- /dev/null
@@ -0,0 +1,37 @@
+#include "pwf.h"
+
+struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size)
+{
+       ssize_t l;
+       char *s;
+       for (;;) {
+               if ((l=getline(line, size, f)) < 0) {
+                       free(*line);
+                       *line = 0;
+                       return 0;
+               }
+               line[0][l-1] = 0;
+
+               s = line[0];
+               pw->pw_name = s++;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; pw->pw_passwd = s;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; pw->pw_uid = atoi(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; pw->pw_gid = atoi(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; pw->pw_gecos = s;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; pw->pw_dir = s;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; pw->pw_shell = s;
+               return pw;
+       }
+}
diff --git a/src/passwd/getspent.c b/src/passwd/getspent.c
new file mode 100644 (file)
index 0000000..8574a48
--- /dev/null
@@ -0,0 +1,14 @@
+#include "pwf.h"
+
+void setspent()
+{
+}
+
+void endspent()
+{
+}
+
+struct spwd *getspent()
+{
+       return 0;
+}
diff --git a/src/passwd/getspnam.c b/src/passwd/getspnam.c
new file mode 100644 (file)
index 0000000..041f896
--- /dev/null
@@ -0,0 +1,17 @@
+#include "pwf.h"
+
+#define LINE_LIM 256
+
+struct spwd *getspnam(const char *name)
+{
+       static struct spwd sp;
+       static char *line;
+       struct spwd *res;
+       int e;
+
+       if (!line) line = malloc(LINE_LIM);
+       if (!line) return 0;
+       e = getspnam_r(name, &sp, line, LINE_LIM, &res);
+       if (e) errno = e;
+       return res;
+}
diff --git a/src/passwd/getspnam_r.c b/src/passwd/getspnam_r.c
new file mode 100644 (file)
index 0000000..1dd39ce
--- /dev/null
@@ -0,0 +1,89 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include "pwf.h"
+
+/* This implementation support Openwall-style TCB passwords in place of
+ * traditional shadow, if the appropriate directories and files exist.
+ * Thus, it is careful to avoid following symlinks or blocking on fifos
+ * which a malicious user might create in place of his or her TCB shadow
+ * file. It also avoids any allocation to prevent memory-exhaustion
+ * attacks via huge TCB shadow files. */
+
+int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct spwd **res)
+{
+       char path[20+NAME_MAX];
+       FILE *f = 0;
+       int rv = 0;
+       int fd;
+       size_t k, l = strlen(name);
+       char *s;
+       int skip = 0;
+
+       *res = 0;
+
+       /* Disallow potentially-malicious user names */
+       if (*name=='.' || strchr(name, '/') || !l)
+               return EINVAL;
+
+       /* Buffer size must at least be able to hold name, plus some.. */
+       if (size < l+100) return ERANGE;
+
+       /* Protect against truncation */
+       if (snprintf(path, sizeof path, "/etc/tcb/%s/shadow", name) >= sizeof path)
+               return EINVAL;
+
+       fd = open(path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK);
+       if (fd >= 0) {
+               f = fdopen(fd, "rb");
+               if (!f) {
+                       close(fd);
+                       return errno;
+               }
+       } else {
+               f = fopen("/etc/shadow", "rb");
+               if (!f) return errno;
+       }
+
+       while (fgets(buf, size, f) && (k=strlen(buf))>0) {
+               if (skip || strncmp(name, buf, l)) {
+                       skip = buf[k-1] != '\n';
+                       continue;
+               }
+               if (buf[k-1] != '\n') {
+                       rv = ERANGE;
+                       break;
+               }
+               buf[k-1] = 0;
+
+               s = buf;
+               sp->sp_namp = s;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_pwdp = s;
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_lstchg = atol(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_min = atol(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_max = atol(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_warn = atol(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_inact = atol(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_expire = atol(s);
+               if (!(s = strchr(s, ':'))) continue;
+
+               *s++ = 0; sp->sp_flag = atol(s);
+               *res = sp;
+               break;
+       }
+       fclose(f);
+       return rv;
+}
diff --git a/src/passwd/lckpwdf.c b/src/passwd/lckpwdf.c
new file mode 100644 (file)
index 0000000..2feda61
--- /dev/null
@@ -0,0 +1,11 @@
+#include <shadow.h>
+
+int lckpwdf()
+{
+       return 0;
+}
+
+int ulckpwdf()
+{
+       return 0;
+}
diff --git a/src/passwd/pwf.h b/src/passwd/pwf.h
new file mode 100644 (file)
index 0000000..0a76ef8
--- /dev/null
@@ -0,0 +1,13 @@
+#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include "libc.h"
+
+struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size);
+struct spwd *__getspent_a(FILE *f, struct spwd *sp, char **line, size_t *size);
+struct group *__getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem);
diff --git a/src/prng/__rand48_step.c b/src/prng/__rand48_step.c
new file mode 100644 (file)
index 0000000..755b4f2
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <inttypes.h>
+
+uint64_t __rand48_step(unsigned short *xi, unsigned short *lc)
+{
+       uint64_t a, x;
+       x = xi[0] | xi[1]<<16 | xi[2]+0ULL<<32;
+       a = lc[0] | lc[1]<<16 | lc[2]+0ULL<<32;
+       x = a*x + lc[3];
+       xi[0] = x;
+       xi[1] = x>>16;
+       xi[2] = x>>32;
+       return x & 0xffffffffffffull;
+}
diff --git a/src/prng/__seed48.c b/src/prng/__seed48.c
new file mode 100644 (file)
index 0000000..05a4539
--- /dev/null
@@ -0,0 +1 @@
+unsigned short __seed48[7] = { 0, 0, 0, 0xe66d, 0xdeec, 0x5, 0xb };
diff --git a/src/prng/drand48.c b/src/prng/drand48.c
new file mode 100644 (file)
index 0000000..d808353
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+#include <inttypes.h>
+
+uint64_t __rand48_step(unsigned short *xi, unsigned short *lc);
+extern unsigned short __seed48[7];
+
+double erand48(unsigned short s[3])
+{
+       union {
+               uint64_t u;
+               double f;
+       } x = { 0x3ff0000000000000ULL | __rand48_step(s, __seed48+3)<<4 };
+       return x.f - 1.0;
+}
+
+double drand48(void)
+{
+       return erand48(__seed48);
+}
diff --git a/src/prng/lcong48.c b/src/prng/lcong48.c
new file mode 100644 (file)
index 0000000..32b27d4
--- /dev/null
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+#include <string.h>
+
+extern unsigned short __seed48[7];
+
+void lcong48(unsigned short p[7])
+{
+       memcpy(__seed48, p, sizeof __seed48);
+}
diff --git a/src/prng/lrand48.c b/src/prng/lrand48.c
new file mode 100644 (file)
index 0000000..a3c4e4e
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+#include <inttypes.h>
+
+uint64_t __rand48_step(unsigned short *xi, unsigned short *lc);
+extern unsigned short __seed48[7];
+
+long nrand48(unsigned short s[3])
+{
+       return __rand48_step(s, __seed48+3) >> 17;
+}
+
+long lrand48(void)
+{
+       return nrand48(__seed48);
+}
diff --git a/src/prng/mrand48.c b/src/prng/mrand48.c
new file mode 100644 (file)
index 0000000..ee650fc
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+#include <inttypes.h>
+
+uint64_t __rand48_step(unsigned short *xi, unsigned short *lc);
+extern unsigned short __seed48[7];
+
+long jrand48(unsigned short s[3])
+{
+       return __rand48_step(s, __seed48+3) >> 16;
+}
+
+long mrand48(void)
+{
+       return jrand48(__seed48);
+}
diff --git a/src/prng/rand.c b/src/prng/rand.c
new file mode 100644 (file)
index 0000000..e3ce634
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+
+static unsigned seed;
+
+void srand(unsigned s)
+{
+       seed = s-1;
+}
+
+int rand(void)
+{
+       return (seed = (seed+1) * 1103515245 + 12345 - 1)+1 & 0x7fffffff;
+}
diff --git a/src/prng/rand_r.c b/src/prng/rand_r.c
new file mode 100644 (file)
index 0000000..e96cfba
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+int rand_r(unsigned *seed)
+{
+       return (*seed = *seed * 1103515245 + 12345) & 0x7fffffff;
+}
diff --git a/src/prng/random.c b/src/prng/random.c
new file mode 100644 (file)
index 0000000..e6b7fd1
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+
+/* FIXME */
+
+long random()
+{
+       return rand();
+}
diff --git a/src/prng/seed48.c b/src/prng/seed48.c
new file mode 100644 (file)
index 0000000..e0699c0
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include <string.h>
+
+extern unsigned short __seed48[7];
+
+unsigned short *seed48(unsigned short *s)
+{
+       static unsigned short p[3];
+       memcpy(p, __seed48, sizeof p);
+       memcpy(__seed48, s, sizeof p);
+       return p;
+}
diff --git a/src/prng/srand48.c b/src/prng/srand48.c
new file mode 100644 (file)
index 0000000..0a56f6a
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+void srand48(long seed)
+{
+       seed48((unsigned short [3]){ 0x330e, seed, seed>>16 });
+}
diff --git a/src/prng/srandom.c b/src/prng/srandom.c
new file mode 100644 (file)
index 0000000..77f4dcb
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+
+/* FIXME */
+
+void srandom(unsigned seed)
+{
+       return srand(seed);
+}
diff --git a/src/process/execl.c b/src/process/execl.c
new file mode 100644 (file)
index 0000000..4c6eaa9
--- /dev/null
@@ -0,0 +1,20 @@
+#include <unistd.h>
+#include <stdarg.h>
+
+int execl(const char *path, ...)
+{
+       int argc;
+       va_list ap;
+       va_start(ap, path);
+       for (argc=0; va_arg(ap, const char *); argc++);
+       va_end(ap);
+       {
+               int i;
+               char *argv[argc+1];
+               va_start(ap, path);
+               for (i=0; i<argc; i++)
+                       argv[i] = va_arg(ap, char *);
+               argv[i] = NULL;
+               return execv(path, argv);
+       }
+}
diff --git a/src/process/execle.c b/src/process/execle.c
new file mode 100644 (file)
index 0000000..37f629d
--- /dev/null
@@ -0,0 +1,22 @@
+#include <unistd.h>
+#include <stdarg.h>
+
+int execle(const char *path, ...)
+{
+       int argc;
+       va_list ap;
+       va_start(ap, path);
+       for (argc=0; va_arg(ap, const char *); argc++);
+       va_end(ap);
+       {
+               int i;
+               char *argv[argc+1];
+               char **envp;
+               va_start(ap, path);
+               for (i=0; i<argc; i++)
+                       argv[i] = va_arg(ap, char *);
+               argv[i] = NULL;
+               envp = va_arg(ap, char **);
+               return execve(path, argv, envp);
+       }
+}
diff --git a/src/process/execlp.c b/src/process/execlp.c
new file mode 100644 (file)
index 0000000..33fb0f7
--- /dev/null
@@ -0,0 +1,20 @@
+#include <unistd.h>
+#include <stdarg.h>
+
+int execlp(const char *file, ...)
+{
+       int argc;
+       va_list ap;
+       va_start(ap, file);
+       for (argc=0; va_arg(ap, const char *); argc++);
+       va_end(ap);
+       {
+               int i;
+               char *argv[argc+1];
+               va_start(ap, file);
+               for (i=0; i<argc; i++)
+                       argv[i] = va_arg(ap, char *);
+               argv[i] = NULL;
+               return execvp(file, argv);
+       }
+}
diff --git a/src/process/execv.c b/src/process/execv.c
new file mode 100644 (file)
index 0000000..2ac0dec
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+
+extern char **__environ;
+
+int execv(const char *path, char *const argv[])
+{
+       return execve(path, argv, __environ);
+}
diff --git a/src/process/execve.c b/src/process/execve.c
new file mode 100644 (file)
index 0000000..2a0b62d
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int execve(const char *path, char *const argv[], char *const envp[])
+{
+       /* do we need to use environ if envp is null? */
+       return syscall3(__NR_execve, (long)path, (long)argv, (long)envp);
+}
diff --git a/src/process/execvp.c b/src/process/execvp.c
new file mode 100644 (file)
index 0000000..d799dda
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+extern char **__environ;
+
+int execvp(const char *file, char *const argv[])
+{
+       const char *p, *z, *path = getenv("PATH");
+       int l;
+
+       if (strchr(file, '/'))
+               return execve(file, argv, __environ);
+
+       /* FIXME: integer overflows */
+       if (!path) path = "/usr/local/bin:/bin:/usr/bin";
+       l = strlen(file) + strlen(path) + 2;
+
+       for(p=path; p && *p; p=z) {
+               char b[l];
+               z = strchr(p, ':');
+               if (z) {
+                       memcpy(b, p, z-p);
+                       b[z++-p] = 0;
+               } else strcpy(b, p);
+               strcat(b, "/");
+               strcat(b, file);
+               if (!access(b, X_OK))
+                       return execve(b, argv, __environ);
+       }
+       errno = ENOENT;
+       return -1;
+}
diff --git a/src/process/fork.c b/src/process/fork.c
new file mode 100644 (file)
index 0000000..1213f0f
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include "syscall.h"
+
+/* FIXME: add support for atfork stupidity */
+
+pid_t fork(void)
+{
+       return syscall0(__NR_fork);
+}
diff --git a/src/process/system.c b/src/process/system.c
new file mode 100644 (file)
index 0000000..0f1c07b
--- /dev/null
@@ -0,0 +1,45 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+int system(const char *cmd)
+{
+       pid_t pid;
+       sigset_t old, new;
+       struct sigaction sa, oldint, oldquit;
+       int status;
+
+       if (!cmd) return 1;
+
+       sa.sa_handler = SIG_IGN;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = 0;
+
+       sigaction(SIGINT, &sa, &oldint);
+       sigaction(SIGQUIT, &sa, &oldquit);
+       sigaddset(&sa.sa_mask, SIGCHLD);
+       sigprocmask(SIG_BLOCK, &new, &old);
+
+       pid = fork();
+       if (pid <= 0) {
+               sigaction(SIGINT, &oldint, NULL);
+               sigaction(SIGQUIT, &oldquit, NULL);
+               sigprocmask(SIG_SETMASK, &old, NULL);
+               if (pid == 0) {
+                       execl("/bin/sh", "sh", "-c", cmd, (char *)0);
+                       _exit(127);
+               }
+               return -1;
+       }
+       while (waitpid(pid, &status, 0) == -1)
+               if (errno != EINTR) {
+                       status = -1;
+                       break;
+               }
+       sigaction(SIGINT, &oldint, NULL);
+       sigaction(SIGQUIT, &oldquit, NULL);
+       sigprocmask(SIG_SETMASK, &old, NULL);
+       return status;
+}
diff --git a/src/process/vfork.c b/src/process/vfork.c
new file mode 100644 (file)
index 0000000..32a7a6e
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t vfork(void)
+{
+       /* vfork syscall cannot be made from C code */
+       return syscall0(__NR_fork);
+}
diff --git a/src/process/wait.c b/src/process/wait.c
new file mode 100644 (file)
index 0000000..34da102
--- /dev/null
@@ -0,0 +1,6 @@
+#include <sys/wait.h>
+
+pid_t wait(int *status)
+{
+       return waitpid((pid_t)-1, status, 0);
+}
diff --git a/src/process/waitid.c b/src/process/waitid.c
new file mode 100644 (file)
index 0000000..0ec0d55
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/wait.h>
+#include "syscall.h"
+
+int waitid(idtype_t type, id_t id, siginfo_t *info, int options)
+{
+       return syscall5(__NR_waitid, type, id, (long)info, options, 0);
+}
diff --git a/src/process/waitpid.c b/src/process/waitpid.c
new file mode 100644 (file)
index 0000000..0ddcd15
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/wait.h>
+#include "syscall.h"
+
+pid_t waitpid(pid_t pid, int *status, int options)
+{
+       return syscall4(__NR_wait4, pid, (long)status, options, 0);
+}
diff --git a/src/regex/fnmatch.c b/src/regex/fnmatch.c
new file mode 100644 (file)
index 0000000..5f2fccd
--- /dev/null
@@ -0,0 +1,150 @@
+#include <fnmatch.h>
+#include <wctype.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdlib.h>
+#include <limits.h>
+
+static int next(const char **s)
+{
+       wchar_t c;
+       int l = mbtowc(&c, *s, MB_LEN_MAX);
+       /* hack to allow literal matches of invalid byte sequences */
+       if (l < 0) return (unsigned char)*(*s)++ - 0x100;
+       *s += l;
+       return c;
+}
+
+#define BRACKET_ERROR  -0x100
+#define BRACKET_NOCHAR -0x101
+
+static int bracket_next(const char **s)
+{
+       int c;
+       int type;
+       if (**s == '[') {
+               type = *(*s+1);
+               if (type == '.' || type == '=') {
+                       *s += 2;
+                       c = next(s);
+                       if (c <= 0) return BRACKET_ERROR;
+                       if (**s == type && *(*s+1) == ']') {
+                               *s += 2;
+                               return c;
+                       }
+                       for (; **s && (**s != type || *(*s+1) != ']'); (*s)++);
+                       if (!**s) return BRACKET_ERROR;
+                       *s += 2;
+                       return BRACKET_NOCHAR;
+               }
+       }
+       c = next(s);
+       if (c <= 0) return BRACKET_ERROR;
+       return c;
+}
+
+#define __FNM_CONT 0x8000
+
+int fnmatch(const char *p, const char *s, int flags)
+{
+       int c, d, k;
+       int not;
+       int match;
+       int first;
+       int no_slash = (flags & FNM_PATHNAME) ? '/' : 0;
+       int no_period = (flags & FNM_PERIOD) && !(flags & __FNM_CONT) ? '.' : 0x100;
+
+       flags |= __FNM_CONT;
+
+       while ((c = *p++)) {
+               switch (c) {
+               case '?':
+                       k = next(&s);
+                       if (!k || k == no_period || k == no_slash)
+                               return FNM_NOMATCH;
+                       break;
+               case '\\':
+                       if (!(flags & FNM_NOESCAPE)) {
+                               c = *p++;
+                               goto literal;
+                       }
+                       if (*s++ != c) return FNM_NOMATCH;
+                       break;
+               case '*':
+                       for (; *p == '*'; p++);
+                       if (*p && !*s) return FNM_NOMATCH;
+                       if (*s == no_period)
+                               return FNM_NOMATCH;
+                       if (!*p && (!no_slash || !strchr(s, no_slash)))
+                               return 0;
+                       for (; *s; s++)
+                               if (!fnmatch(p, s, flags))
+                                       return 0;
+                               else if (*s == no_slash)
+                                       break;
+                       return FNM_NOMATCH;
+               case '[':
+                       not = (*p == '!' || *p == '^');
+                       if (not) p++;
+                       k = next(&s);
+                       if (!k || k == no_slash || k == no_period)
+                               return FNM_NOMATCH;
+                       match = 0;
+                       first = 1;
+                       for (;;) {
+                               if (!*p) return FNM_NOMATCH;
+                               if (*p == ']' && !first) break;
+                               first = 0;
+                               if (*p == '[' && *(p+1) == ':') {
+                                       const char *z;
+                                       p += 2;
+                                       for (z=p; *z && (*z != ':' || *(z+1) != ']'); z++);
+                                       if (!*z || z-p > 32) { /* FIXME: symbolic const? */
+                                               return FNM_NOMATCH;
+                                       } else {
+                                               char class[z-p+1];
+                                               memcpy(class, p, z-p);
+                                               class[z-p] = 0;
+                                               if (iswctype(k, wctype(class)))
+                                                       match = 1;
+                                       }
+                                       p = z+2;
+                                       continue;
+                               }
+                               c = bracket_next(&p);
+                               if (c == BRACKET_ERROR)
+                                       return FNM_NOMATCH;
+                               if (c == BRACKET_NOCHAR)
+                                       continue;
+                               if (*p == '-' && *(p+1) != ']') {
+                                       p++;
+                                       d = bracket_next(&p);
+                                       if (d == BRACKET_ERROR)
+                                               return FNM_NOMATCH;
+                                       if (d == BRACKET_NOCHAR)
+                                               continue;
+                                       if (k >= c && k <= d)
+                                               match = 1;
+                                       continue;
+                               }
+                               if (k == c) match = 1;
+                       }
+                       p++;
+                       if (not == match)
+                               return FNM_NOMATCH;
+                       break;
+               default:
+               literal:
+                       if (*s++ != c)
+                               return FNM_NOMATCH;
+                       if (c == no_slash && (flags & FNM_PERIOD)) {
+                               no_period = '.';
+                               continue;
+                       }
+                       break;
+               }
+               no_period = 0x100;
+       }
+       if (*s) return FNM_NOMATCH;
+       return 0;
+}
diff --git a/src/regex/glob.c b/src/regex/glob.c
new file mode 100644 (file)
index 0000000..9a70f0b
--- /dev/null
@@ -0,0 +1,238 @@
+#include <glob.h>
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "libc.h"
+
+struct match
+{
+       struct match *next;
+       char name[1];
+};
+
+static int is_literal(const char *p, int useesc)
+{
+       int bracket = 0;
+       for (; *p; p++) {
+               switch (*p) {
+               case '\\':
+                       if (!useesc) break;
+               case '?':
+               case '*':
+                       return 0;
+               case '[':
+                       bracket = 1;
+                       break;
+               case ']':
+                       if (bracket) return 0;
+                       break;
+               }
+       }
+       return 1;
+}
+
+static int append(struct match **tail, const char *name, size_t len, int mark)
+{
+       struct match *new = malloc(sizeof(struct match) + len + 1);
+       if (!new) return -1;
+       (*tail)->next = new;
+       new->next = NULL;
+       strcpy(new->name, name);
+       if (mark) strcat(new->name, "/");
+       *tail = new;
+       return 0;
+}
+
+static int match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail)
+{
+       DIR *dir;
+       long long de_buf[(sizeof(struct dirent) + NAME_MAX + sizeof(long long))/sizeof(long long)];
+       struct dirent *de;
+       char pat[strlen(p)+1];
+       char *p2;
+       size_t l = strlen(d);
+       int literal;
+       int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) | FNM_PERIOD;
+       int error;
+
+       if ((p2 = strchr(p, '/'))) {
+               strcpy(pat, p);
+               pat[p2-p] = 0;
+               for (; *p2 == '/'; p2++);
+               p = pat;
+       }
+       literal = is_literal(p, !(flags & GLOB_NOESCAPE));
+       if (*d == '/' && !*(d+1)) l = 0;
+
+       /* rely on opendir failing for nondirectory objects */
+       dir = opendir(*d ? d : ".");
+       error = errno;
+       if (!dir) {
+               /* this is not an error -- we let opendir call stat for us */
+               if (error == ENOTDIR) return 0;
+               if (error == EACCES && !*p) {
+                       struct stat st;
+                       if (!stat(d, &st) && S_ISDIR(st.st_mode)) {
+                               if (append(tail, d, l, l))
+                                       return GLOB_NOSPACE;
+                               return 0;
+                       }
+               }
+               if (errfunc(d, error) || (flags & GLOB_ERR))
+                       return GLOB_ABORTED;
+               return 0;
+       }
+       if (!*p) {
+               error = append(tail, d, l, l) ? GLOB_NOSPACE : 0;
+               closedir(dir);
+               return error;
+       }
+       while (!(error = readdir_r(dir, (void *)de_buf, &de)) && de) {
+               char namebuf[l+de->d_reclen+2], *name = namebuf;
+               if (!literal && fnmatch(p, de->d_name, fnm_flags))
+                       continue;
+               if (literal && strcmp(p, de->d_name))
+                       continue;
+               if (p2 && de->d_type && !S_ISDIR(de->d_type<<12) && !S_ISLNK(de->d_type<<12))
+                       continue;
+               if (*d) {
+                       memcpy(name, d, l);
+                       name[l] = '/';
+                       strcpy(name+l+1, de->d_name);
+               } else {
+                       name = de->d_name;
+               }
+               if (p2) {
+                       if ((error = match_in_dir(name, p2, flags, errfunc, tail))) {
+                               closedir(dir);
+                               return error;
+                       }
+               } else {
+                       int mark = 0;
+                       if (flags & GLOB_MARK) {
+                               if (de->d_type)
+                                       mark = S_ISDIR(de->d_type<<12);
+                               else {
+                                       struct stat st;
+                                       stat(name, &st);
+                                       mark = S_ISDIR(st.st_mode);
+                               }
+                       }
+                       if (append(tail, name, l+de->d_reclen+1, mark)) {
+                               closedir(dir);
+                               return GLOB_NOSPACE;
+                       }
+               }
+       }
+       closedir(dir);
+       if (error && (errfunc(d, error) || (flags & GLOB_ERR)))
+               return GLOB_ABORTED;
+       return 0;
+}
+
+static int ignore_err(const char *path, int err)
+{
+       return 0;
+}
+
+static void freelist(struct match *head)
+{
+       struct match *match, *next;
+       for (match=head->next; match; match=next) {
+               next = match->next;
+               free(match);
+       }
+}
+
+static int sort(const void *a, const void *b)
+{
+       return strcmp(*(const char **)a, *(const char **)b);
+}
+
+int glob(const char *pat, int flags, int (*errfunc)(const char *path, int err), glob_t *g)
+{
+       const char *p=pat, *d;
+       struct match head = { .next = NULL }, *tail = &head;
+       size_t cnt, i;
+       size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
+       int error = 0;
+       
+       if (*p == '/') {
+               for (; *p == '/'; p++);
+               d = "/";
+       } else {
+               d = "";
+       }
+
+       if (!errfunc) errfunc = ignore_err;
+
+       if (!(flags & GLOB_APPEND)) {
+               g->gl_offs = offs;
+               g->gl_pathc = 0;
+               g->gl_pathv = NULL;
+       }
+
+       if (*p) error = match_in_dir(d, p, flags, errfunc, &tail);
+       if (error == GLOB_NOSPACE) {
+               freelist(&head);
+               return error;
+       }
+       
+       for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++);
+       if (!cnt) {
+               if (flags & GLOB_NOCHECK) {
+                       tail = &head;
+                       if (append(&tail, pat, strlen(pat), 0))
+                               return GLOB_NOSPACE;
+                       cnt++;
+               } else
+                       return GLOB_NOMATCH;
+       }
+
+       if (flags & GLOB_APPEND) {
+               char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
+               if (!pathv) {
+                       freelist(&head);
+                       return GLOB_NOSPACE;
+               }
+               g->gl_pathv = pathv;
+               offs += g->gl_pathc;
+       } else {
+               g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
+               if (!g->gl_pathv) {
+                       freelist(&head);
+                       return GLOB_NOSPACE;
+               }
+               for (i=0; i<offs; i++)
+                       g->gl_pathv[i] = NULL;
+       }
+       for (i=0, tail=head.next; i<cnt; tail=tail->next, i++)
+               g->gl_pathv[offs + i] = tail->name;
+       g->gl_pathv[offs + i] = NULL;
+       g->gl_pathc += cnt;
+
+       if (!(flags & GLOB_NOSORT))
+               qsort(g->gl_pathv+offs, cnt, sizeof(char *), sort);
+       
+       return error;
+}
+
+void globfree(glob_t *g)
+{
+       size_t i;
+       for (i=0; i<g->gl_pathc; i++)
+               free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name));
+       free(g->gl_pathv);
+       g->gl_pathc = 0;
+       g->gl_pathv = NULL;
+}
+
+LFS64(glob);
+LFS64(globfree);
diff --git a/src/regex/regcomp.c b/src/regex/regcomp.c
new file mode 100644 (file)
index 0000000..3307942
--- /dev/null
@@ -0,0 +1,3362 @@
+/*
+  regcomp.c - TRE POSIX compatible regex compilation functions.
+
+  Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <regex.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "tre.h"
+
+#include <assert.h>
+
+/***********************************************************************
+ from tre-ast.c and tre-ast.h
+***********************************************************************/
+
+/* The different AST node types. */
+typedef enum {
+  LITERAL,
+  CATENATION,
+  ITERATION,
+  UNION
+} tre_ast_type_t;
+
+/* Special subtypes of TRE_LITERAL. */
+#define EMPTY    -1   /* Empty leaf (denotes empty string). */
+#define ASSERTION -2   /* Assertion leaf. */
+#define TAG      -3   /* Tag leaf. */
+#define BACKREF          -4   /* Back reference leaf. */
+
+#define IS_SPECIAL(x)  ((x)->code_min < 0)
+#define IS_EMPTY(x)    ((x)->code_min == EMPTY)
+#define IS_ASSERTION(x) ((x)->code_min == ASSERTION)
+#define IS_TAG(x)      ((x)->code_min == TAG)
+#define IS_BACKREF(x)  ((x)->code_min == BACKREF)
+
+/* Taken from tre-compile.h */
+typedef struct {
+  int position;
+  int code_min;
+  int code_max;
+  int *tags;
+  int assertions;
+  tre_ctype_t class;
+  tre_ctype_t *neg_classes;
+  int backref;
+} tre_pos_and_tags_t;
+
+/* A generic AST node.  All AST nodes consist of this node on the top
+   level with `obj' pointing to the actual content. */
+typedef struct {
+  tre_ast_type_t type;   /* Type of the node. */
+  void *obj;             /* Pointer to actual node. */
+  int nullable;
+  int submatch_id;
+  int num_submatches;
+  int num_tags;
+  tre_pos_and_tags_t *firstpos;
+  tre_pos_and_tags_t *lastpos;
+} tre_ast_node_t;
+
+
+/* A "literal" node.  These are created for assertions, back references,
+   tags, matching parameter settings, and all expressions that match one
+   character. */
+typedef struct {
+  long code_min;
+  long code_max;
+  int position;
+  tre_ctype_t class;
+  tre_ctype_t *neg_classes;
+} tre_literal_t;
+
+/* A "catenation" node.         These are created when two regexps are concatenated.
+   If there are more than one subexpressions in sequence, the `left' part
+   holds all but the last, and `right' part holds the last subexpression
+   (catenation is left associative). */
+typedef struct {
+  tre_ast_node_t *left;
+  tre_ast_node_t *right;
+} tre_catenation_t;
+
+/* An "iteration" node.         These are created for the "*", "+", "?", and "{m,n}"
+   operators. */
+typedef struct {
+  /* Subexpression to match. */
+  tre_ast_node_t *arg;
+  /* Minimum number of consecutive matches. */
+  int min;
+  /* Maximum number of consecutive matches. */
+  int max;
+} tre_iteration_t;
+
+/* An "union" node.  These are created for the "|" operator. */
+typedef struct {
+  tre_ast_node_t *left;
+  tre_ast_node_t *right;
+} tre_union_t;
+
+static tre_ast_node_t *
+tre_ast_new_node(tre_mem_t mem, tre_ast_type_t type, size_t size)
+{
+  tre_ast_node_t *node;
+
+  node = tre_mem_calloc(mem, sizeof(*node));
+  if (!node)
+    return NULL;
+  node->obj = tre_mem_calloc(mem, size);
+  if (!node->obj)
+    return NULL;
+  node->type = type;
+  node->nullable = -1;
+  node->submatch_id = -1;
+
+  return node;
+}
+
+static tre_ast_node_t *
+tre_ast_new_literal(tre_mem_t mem, int code_min, int code_max, int position)
+{
+  tre_ast_node_t *node;
+  tre_literal_t *lit;
+
+  node = tre_ast_new_node(mem, LITERAL, sizeof(tre_literal_t));
+  if (!node)
+    return NULL;
+  lit = node->obj;
+  lit->code_min = code_min;
+  lit->code_max = code_max;
+  lit->position = position;
+
+  return node;
+}
+
+static tre_ast_node_t *
+tre_ast_new_iter(tre_mem_t mem, tre_ast_node_t *arg, int min, int max)
+{
+  tre_ast_node_t *node;
+  tre_iteration_t *iter;
+
+  node = tre_ast_new_node(mem, ITERATION, sizeof(tre_iteration_t));
+  if (!node)
+    return NULL;
+  iter = node->obj;
+  iter->arg = arg;
+  iter->min = min;
+  iter->max = max;
+  node->num_submatches = arg->num_submatches;
+
+  return node;
+}
+
+static tre_ast_node_t *
+tre_ast_new_union(tre_mem_t mem, tre_ast_node_t *left, tre_ast_node_t *right)
+{
+  tre_ast_node_t *node;
+
+  node = tre_ast_new_node(mem, UNION, sizeof(tre_union_t));
+  if (node == NULL)
+    return NULL;
+  ((tre_union_t *)node->obj)->left = left;
+  ((tre_union_t *)node->obj)->right = right;
+  node->num_submatches = left->num_submatches + right->num_submatches;
+
+  return node;
+}
+
+static tre_ast_node_t *
+tre_ast_new_catenation(tre_mem_t mem, tre_ast_node_t *left,
+                      tre_ast_node_t *right)
+{
+  tre_ast_node_t *node;
+
+  node = tre_ast_new_node(mem, CATENATION, sizeof(tre_catenation_t));
+  if (node == NULL)
+    return NULL;
+  ((tre_catenation_t *)node->obj)->left = left;
+  ((tre_catenation_t *)node->obj)->right = right;
+  node->num_submatches = left->num_submatches + right->num_submatches;
+
+  return node;
+}
+
+/***********************************************************************
+ from tre-stack.c and tre-stack.h
+***********************************************************************/
+
+/* Just to save some typing. */
+#define STACK_PUSH(s, value)                                                 \
+  do                                                                         \
+    {                                                                        \
+      status = tre_stack_push(s, (void *)(value));                           \
+    }                                                                        \
+  while (0)
+
+#define STACK_PUSHX(s, value)                                                \
+  {                                                                          \
+    status = tre_stack_push(s, (void *)(value));                             \
+    if (status != REG_OK)                                                    \
+      break;                                                                 \
+  }
+
+#define STACK_PUSHR(s, value)                                                \
+  {                                                                          \
+    reg_errcode_t status;                                                    \
+    status = tre_stack_push(s, (void *)(value));                             \
+    if (status != REG_OK)                                                    \
+      return status;                                                         \
+  }
+
+typedef struct tre_stack_rec {
+  int size;
+  int max_size;
+  int increment;
+  int ptr;
+  void **stack;
+} tre_stack_t;
+
+
+static tre_stack_t *
+tre_stack_new(int size, int max_size, int increment)
+{
+  tre_stack_t *s;
+
+  s = xmalloc(sizeof(*s));
+  if (s != NULL)
+    {
+      s->stack = xmalloc(sizeof(*s->stack) * size);
+      if (s->stack == NULL)
+       {
+         xfree(s);
+         return NULL;
+       }
+      s->size = size;
+      s->max_size = max_size;
+      s->increment = increment;
+      s->ptr = 0;
+    }
+  return s;
+}
+
+static void
+tre_stack_destroy(tre_stack_t *s)
+{
+  xfree(s->stack);
+  xfree(s);
+}
+
+static int
+tre_stack_num_objects(tre_stack_t *s)
+{
+  return s->ptr;
+}
+
+static reg_errcode_t
+tre_stack_push(tre_stack_t *s, void *value)
+{
+  if (s->ptr < s->size)
+    {
+      s->stack[s->ptr] = value;
+      s->ptr++;
+    }
+  else
+    {
+      if (s->size >= s->max_size)
+       {
+         DPRINT(("tre_stack_push: stack full\n"));
+         return REG_ESPACE;
+       }
+      else
+       {
+         void **new_buffer;
+         int new_size;
+         DPRINT(("tre_stack_push: trying to realloc more space\n"));
+         new_size = s->size + s->increment;
+         if (new_size > s->max_size)
+           new_size = s->max_size;
+         new_buffer = xrealloc(s->stack, sizeof(*new_buffer) * new_size);
+         if (new_buffer == NULL)
+           {
+             DPRINT(("tre_stack_push: realloc failed.\n"));
+             return REG_ESPACE;
+           }
+         DPRINT(("tre_stack_push: realloc succeeded.\n"));
+         assert(new_size > s->size);
+         s->size = new_size;
+         s->stack = new_buffer;
+         tre_stack_push(s, value);
+       }
+    }
+  return REG_OK;
+}
+
+static void *
+tre_stack_pop(tre_stack_t *s)
+{
+  return s->stack[--s->ptr];
+}
+
+
+/***********************************************************************
+ from tre-parse.c and tre-parse.h
+***********************************************************************/
+
+/* Parse context. */
+typedef struct {
+  /* Memory allocator. The AST is allocated using this. */
+  tre_mem_t mem;
+  /* Stack used for keeping track of regexp syntax. */
+  tre_stack_t *stack;
+  /* The parse result. */
+  tre_ast_node_t *result;
+  /* The regexp to parse and its length. */
+  const tre_char_t *re;
+  /* The first character of the entire regexp. */
+  const tre_char_t *re_start;
+  /* The first character after the end of the regexp. */
+  const tre_char_t *re_end;
+  int len;
+  /* Current submatch ID. */
+  int submatch_id;
+  /* Current position (number of literal). */
+  int position;
+  /* The highest back reference or -1 if none seen so far. */
+  int max_backref;
+  /* Compilation flags. */
+  int cflags;
+  /* If this flag is set the top-level submatch is not captured. */
+  int nofirstsub;
+} tre_parse_ctx_t;
+
+static reg_errcode_t
+tre_new_item(tre_mem_t mem, int min, int max, int *i, int *max_i,
+        tre_ast_node_t ***items)
+{
+  reg_errcode_t status;
+  tre_ast_node_t **array = *items;
+  /* Allocate more space if necessary. */
+  if (*i >= *max_i)
+    {
+      tre_ast_node_t **new_items;
+      DPRINT(("out of array space, i = %d\n", *i));
+      /* If the array is already 1024 items large, give up -- there's
+        probably an error in the regexp (e.g. not a '\0' terminated
+        string and missing ']') */
+      if (*max_i > 1024)
+       return REG_ESPACE;
+      *max_i *= 2;
+      new_items = xrealloc(array, sizeof(*items) * *max_i);
+      if (new_items == NULL)
+       return REG_ESPACE;
+      *items = array = new_items;
+    }
+  array[*i] = tre_ast_new_literal(mem, min, max, -1);
+  status = array[*i] == NULL ? REG_ESPACE : REG_OK;
+  (*i)++;
+  return status;
+}
+
+
+/* Expands a character class to character ranges. */
+static reg_errcode_t
+tre_expand_ctype(tre_mem_t mem, tre_ctype_t class, tre_ast_node_t ***items,
+                int *i, int *max_i, int cflags)
+{
+  reg_errcode_t status = REG_OK;
+  tre_cint_t c;
+  int j, min = -1, max = 0;
+  assert(TRE_MB_CUR_MAX == 1);
+
+  DPRINT(("  expanding class to character ranges\n"));
+  for (j = 0; (j < 256) && (status == REG_OK); j++)
+    {
+      c = j;
+      if (tre_isctype(c, class)
+         || ((cflags & REG_ICASE)
+             && (tre_isctype(tre_tolower(c), class)
+                 || tre_isctype(tre_toupper(c), class))))
+{
+         if (min < 0)
+           min = c;
+         max = c;
+       }
+      else if (min >= 0)
+       {
+         DPRINT(("  range %c (%d) to %c (%d)\n", min, min, max, max));
+         status = tre_new_item(mem, min, max, i, max_i, items);
+         min = -1;
+       }
+    }
+  if (min >= 0 && status == REG_OK)
+    status = tre_new_item(mem, min, max, i, max_i, items);
+  return status;
+}
+
+
+static int
+tre_compare_items(const void *a, const void *b)
+{
+  tre_ast_node_t *node_a = *(tre_ast_node_t **)a;
+  tre_ast_node_t *node_b = *(tre_ast_node_t **)b;
+  tre_literal_t *l_a = node_a->obj, *l_b = node_b->obj;
+  int a_min = l_a->code_min, b_min = l_b->code_min;
+
+  if (a_min < b_min)
+    return -1;
+  else if (a_min > b_min)
+    return 1;
+  else
+    return 0;
+}
+
+/* Maximum number of character classes that can occur in a negated bracket
+   expression. */
+#define MAX_NEG_CLASSES 64
+
+/* Maximum length of character class names. */
+#define MAX_CLASS_NAME
+
+static reg_errcode_t
+tre_parse_bracket_items(tre_parse_ctx_t *ctx, int negate,
+                       tre_ctype_t neg_classes[], int *num_neg_classes,
+                       tre_ast_node_t ***items, int *num_items,
+                       int *items_size)
+{
+  const tre_char_t *re = ctx->re;
+  reg_errcode_t status = REG_OK;
+  tre_ctype_t class = (tre_ctype_t)0;
+  int i = *num_items;
+  int max_i = *items_size;
+  int skip;
+
+  /* Build an array of the items in the bracket expression. */
+  while (status == REG_OK)
+    {
+      skip = 0;
+      if (re == ctx->re_end)
+       {
+         status = REG_EBRACK;
+       }
+      else if (*re == ']' && re > ctx->re)
+       {
+         DPRINT(("tre_parse_bracket:   done: '%.*" STRF "'\n",
+                 ctx->re_end - re, re));
+         re++;
+         break;
+       }
+      else
+       {
+         tre_cint_t min = 0, max = 0;
+
+         class = (tre_ctype_t)0;
+         if (re + 2 < ctx->re_end
+             && *(re + 1) == '-' && *(re + 2) != ']')
+           {
+             DPRINT(("tre_parse_bracket:  range: '%.*" STRF "'\n",
+                     ctx->re_end - re, re));
+             min = *re;
+             max = *(re + 2);
+             re += 3;
+             /* XXX - Should use collation order instead of encoding values
+                in character ranges. */
+             if (min > max)
+               status = REG_ERANGE;
+           }
+         else if (re + 1 < ctx->re_end
+                  && *re == '[' && *(re + 1) == '.')
+           status = REG_ECOLLATE;
+         else if (re + 1 < ctx->re_end
+                  && *re == '[' && *(re + 1) == '=')
+           status = REG_ECOLLATE;
+         else if (re + 1 < ctx->re_end
+                  && *re == '[' && *(re + 1) == ':')
+           {
+             char tmp_str[64];
+             const tre_char_t *endptr = re + 2;
+             int len;
+             DPRINT(("tre_parse_bracket:  class: '%.*" STRF "'\n",
+                     ctx->re_end - re, re));
+             while (endptr < ctx->re_end && *endptr != ':')
+               endptr++;
+             if (endptr != ctx->re_end)
+               {
+                 len = MIN(endptr - re - 2, 63);
+#ifdef TRE_WCHAR
+                 {
+                   tre_char_t tmp_wcs[64];
+                   wcsncpy(tmp_wcs, re + 2, len);
+                   tmp_wcs[len] = '\0';
+#if defined HAVE_WCSRTOMBS
+                   {
+                     mbstate_t state;
+                     const tre_char_t *src = tmp_wcs;
+                     memset(&state, '\0', sizeof(state));
+                     len = wcsrtombs(tmp_str, &src, sizeof(tmp_str), &state);
+                   }
+#elif defined HAVE_WCSTOMBS
+                   len = wcstombs(tmp_str, tmp_wcs, 63);
+#endif /* defined HAVE_WCSTOMBS */
+                 }
+#else /* !TRE_WCHAR */
+                 strncpy(tmp_str, re + 2, len);
+#endif /* !TRE_WCHAR */
+                 tmp_str[len] = '\0';
+                 DPRINT(("  class name: %s\n", tmp_str));
+                 class = tre_ctype(tmp_str);
+                 if (!class)
+                   status = REG_ECTYPE;
+                 /* Optimize character classes for 8 bit character sets. */
+                 if (status == REG_OK && TRE_MB_CUR_MAX == 1)
+                   {
+                     status = tre_expand_ctype(ctx->mem, class, items,
+                                               &i, &max_i, ctx->cflags);
+                     class = (tre_ctype_t)0;
+                     skip = 1;
+                   }
+                 re = endptr + 2;
+               }
+             else
+               status = REG_ECTYPE;
+             min = 0;
+             max = TRE_CHAR_MAX;
+           }
+         else
+           {
+             DPRINT(("tre_parse_bracket:   char: '%.*" STRF "'\n",
+                     ctx->re_end - re, re));
+             if (*re == '-' && *(re + 1) != ']'
+                 && ctx->re != re)
+               /* Two ranges are not allowed to share and endpoint. */
+               status = REG_ERANGE;
+             min = max = *re++;
+           }
+
+         if (status != REG_OK)
+           break;
+
+         if (class && negate)
+           if (*num_neg_classes >= MAX_NEG_CLASSES)
+             status = REG_ESPACE;
+           else
+             neg_classes[(*num_neg_classes)++] = class;
+         else if (!skip)
+           {
+             status = tre_new_item(ctx->mem, min, max, &i, &max_i, items);
+             if (status != REG_OK)
+               break;
+             ((tre_literal_t*)((*items)[i-1])->obj)->class = class;
+           }
+
+         /* Add opposite-case counterpoints if REG_ICASE is present.
+            This is broken if there are more than two "same" characters. */
+         if (ctx->cflags & REG_ICASE && !class && status == REG_OK && !skip)
+           {
+             int cmin, ccurr;
+
+             DPRINT(("adding opposite-case counterpoints\n"));
+             while (min <= max)
+               {
+                 if (tre_islower(min))
+                   {
+                     cmin = ccurr = tre_toupper(min++);
+                     while (tre_islower(min) && tre_toupper(min) == ccurr + 1
+                            && min <= max)
+                       ccurr = tre_toupper(min++);
+                     status = tre_new_item(ctx->mem, cmin, ccurr,
+                                           &i, &max_i, items);
+                   }
+                 else if (tre_isupper(min))
+                   {
+                     cmin = ccurr = tre_tolower(min++);
+                     while (tre_isupper(min) && tre_tolower(min) == ccurr + 1
+                            && min <= max)
+                       ccurr = tre_tolower(min++);
+                     status = tre_new_item(ctx->mem, cmin, ccurr,
+                                           &i, &max_i, items);
+                   }
+                 else min++;
+                 if (status != REG_OK)
+                   break;
+               }
+             if (status != REG_OK)
+               break;
+           }
+       }
+    }
+  *num_items = i;
+  *items_size = max_i;
+  ctx->re = re;
+  return status;
+}
+
+static reg_errcode_t
+tre_parse_bracket(tre_parse_ctx_t *ctx, tre_ast_node_t **result)
+{
+  tre_ast_node_t *node = NULL;
+  int negate = 0;
+  reg_errcode_t status = REG_OK;
+  tre_ast_node_t **items, *u, *n;
+  int i = 0, j, max_i = 32, curr_max, curr_min;
+  tre_ctype_t neg_classes[MAX_NEG_CLASSES];
+  int num_neg_classes = 0;
+
+  /* Start off with an array of `max_i' elements. */
+  items = xmalloc(sizeof(*items) * max_i);
+  if (items == NULL)
+    return REG_ESPACE;
+
+  if (*ctx->re == '^')
+    {
+      DPRINT(("tre_parse_bracket: negate: '%.*" STRF "'\n",
+             ctx->re_end - ctx->re, ctx->re));
+      negate = 1;
+      ctx->re++;
+    }
+
+  status = tre_parse_bracket_items(ctx, negate, neg_classes, &num_neg_classes,
+                                  &items, &i, &max_i);
+
+  if (status != REG_OK)
+    goto parse_bracket_done;
+
+  /* Sort the array if we need to negate it. */
+  if (negate)
+    qsort(items, i, sizeof(*items), tre_compare_items);
+
+  curr_max = curr_min = 0;
+  /* Build a union of the items in the array, negated if necessary. */
+  for (j = 0; j < i && status == REG_OK; j++)
+    {
+      int min, max;
+      tre_literal_t *l = items[j]->obj;
+      min = l->code_min;
+      max = l->code_max;
+
+      DPRINT(("item: %d - %d, class %ld, curr_max = %d\n",
+             (int)l->code_min, (int)l->code_max, (long)l->class, curr_max));
+
+      if (negate)
+       {
+         if (min < curr_max)
+           {
+             /* Overlap. */
+             curr_max = MAX(max + 1, curr_max);
+             DPRINT(("overlap, curr_max = %d\n", curr_max));
+             l = NULL;
+           }
+         else
+           {
+             /* No overlap. */
+             curr_max = min - 1;
+             if (curr_max >= curr_min)
+               {
+                 DPRINT(("no overlap\n"));
+                 l->code_min = curr_min;
+                 l->code_max = curr_max;
+               }
+             else
+               {
+                 DPRINT(("no overlap, zero room\n"));
+                 l = NULL;
+               }
+             curr_min = curr_max = max + 1;
+           }
+       }
+
+      if (l != NULL)
+       {
+         int k;
+         DPRINT(("creating %d - %d\n", (int)l->code_min, (int)l->code_max));
+         l->position = ctx->position;
+         if (num_neg_classes > 0)
+           {
+             l->neg_classes = tre_mem_alloc(ctx->mem,
+                                            (sizeof(l->neg_classes)
+                                             * (num_neg_classes + 1)));
+             if (l->neg_classes == NULL)
+               {
+                 status = REG_ESPACE;
+                 break;
+               }
+             for (k = 0; k < num_neg_classes; k++)
+               l->neg_classes[k] = neg_classes[k];
+             l->neg_classes[k] = (tre_ctype_t)0;
+           }
+         else
+           l->neg_classes = NULL;
+         if (node == NULL)
+           node = items[j];
+         else
+           {
+             u = tre_ast_new_union(ctx->mem, node, items[j]);
+             if (u == NULL)
+               status = REG_ESPACE;
+             node = u;
+           }
+       }
+    }
+
+  if (status != REG_OK)
+    goto parse_bracket_done;
+
+  if (negate)
+    {
+      int k;
+      DPRINT(("final: creating %d - %d\n", curr_min, (int)TRE_CHAR_MAX));
+      n = tre_ast_new_literal(ctx->mem, curr_min, TRE_CHAR_MAX, ctx->position);
+      if (n == NULL)
+       status = REG_ESPACE;
+      else
+       {
+         tre_literal_t *l = n->obj;
+         if (num_neg_classes > 0)
+           {
+             l->neg_classes = tre_mem_alloc(ctx->mem,
+                                            (sizeof(l->neg_classes)
+                                             * (num_neg_classes + 1)));
+             if (l->neg_classes == NULL)
+               {
+                 status = REG_ESPACE;
+                 goto parse_bracket_done;
+               }
+             for (k = 0; k < num_neg_classes; k++)
+               l->neg_classes[k] = neg_classes[k];
+             l->neg_classes[k] = (tre_ctype_t)0;
+           }
+         else
+           l->neg_classes = NULL;
+         if (node == NULL)
+           node = n;
+         else
+           {
+             u = tre_ast_new_union(ctx->mem, node, n);
+             if (u == NULL)
+               status = REG_ESPACE;
+             node = u;
+           }
+       }
+    }
+
+  if (status != REG_OK)
+    goto parse_bracket_done;
+
+#ifdef TRE_DEBUG
+  tre_ast_print(node);
+#endif /* TRE_DEBUG */
+
+ parse_bracket_done:
+  xfree(items);
+  ctx->position++;
+  *result = node;
+  return status;
+}
+
+
+/* Parses a positive decimal integer.  Returns -1 if the string does not
+   contain a valid number. */
+static int
+tre_parse_int(const tre_char_t **regex, const tre_char_t *regex_end)
+{
+  int num = -1;
+  const tre_char_t *r = *regex;
+  while (r < regex_end && *r >= '0' && *r <= '9')
+    {
+      if (num < 0)
+       num = 0;
+      num = num * 10 + *r - '0';
+      r++;
+    }
+  *regex = r;
+  return num;
+}
+
+
+static reg_errcode_t
+tre_parse_bound(tre_parse_ctx_t *ctx, tre_ast_node_t **result)
+{
+  int min, max;
+  const tre_char_t *r = ctx->re;
+  const tre_char_t *start;
+  int counts_set = 0;
+
+  /* Parse number (minimum repetition count). */
+  min = -1;
+  if (r < ctx->re_end && *r >= '0' && *r <= '9') {
+    DPRINT(("tre_parse:          min count: '%.*" STRF "'\n", ctx->re_end - r, r));
+    min = tre_parse_int(&r, ctx->re_end);
+  }
+
+  /* Parse comma and second number (maximum repetition count). */
+  max = min;
+  if (r < ctx->re_end && *r == ',')
+    {
+      r++;
+      DPRINT(("tre_parse:   max count: '%.*" STRF "'\n", ctx->re_end - r, r));
+      max = tre_parse_int(&r, ctx->re_end);
+    }
+
+  /* Check that the repeat counts are sane. */
+  if ((max >= 0 && min > max) || max > RE_DUP_MAX)
+    return REG_BADBR;
+
+
+  /*
+   '{'
+     optionally followed immediately by a number == minimum repcount
+     optionally followed by , then a number == maximum repcount
+  */
+
+
+  do {
+    int done;
+    start = r;
+
+    /* Parse count limit settings */
+    done = 0;
+    if (!counts_set)
+      while (r + 1 < ctx->re_end && !done)
+       {
+         switch (*r)
+           {
+           case ',':
+             r++;
+             break;
+           case ' ':
+             r++;
+             break;
+           case '}':
+             done = 1;
+             break;
+           default:
+             done = 1;
+             break;
+           }
+       }
+  } while (start != r);
+
+  /* Missing }. */
+  if (r >= ctx->re_end)
+    return REG_EBRACE;
+
+  /* Empty contents of {}. */
+  if (r == ctx->re)
+    return REG_BADBR;
+
+  /* Parse the ending '}' or '\}'.*/
+  if (ctx->cflags & REG_EXTENDED)
+    {
+      if (r >= ctx->re_end || *r != '}')
+       return REG_BADBR;
+      r++;
+    }
+  else
+    {
+      if (r + 1 >= ctx->re_end
+         || *r != '\\'
+         || *(r + 1) != '}')
+       return REG_BADBR;
+      r += 2;
+    }
+
+
+  /* Create the AST node(s). */
+  if (min == 0 && max == 0)
+    {
+      *result = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1);
+      if (*result == NULL)
+       return REG_ESPACE;
+    }
+  else
+    {
+      if (min < 0 && max < 0)
+       /* Only approximate parameters set, no repetitions. */
+       min = max = 1;
+
+      *result = tre_ast_new_iter(ctx->mem, *result, min, max);
+      if (!*result)
+       return REG_ESPACE;
+    }
+
+  ctx->re = r;
+  return REG_OK;
+}
+
+typedef enum {
+  PARSE_RE = 0,
+  PARSE_ATOM,
+  PARSE_MARK_FOR_SUBMATCH,
+  PARSE_BRANCH,
+  PARSE_PIECE,
+  PARSE_CATENATION,
+  PARSE_POST_CATENATION,
+  PARSE_UNION,
+  PARSE_POST_UNION,
+  PARSE_POSTFIX,
+  PARSE_RESTORE_CFLAGS
+} tre_parse_re_stack_symbol_t;
+
+
+static reg_errcode_t
+tre_parse(tre_parse_ctx_t *ctx)
+{
+  tre_ast_node_t *result = NULL;
+  tre_parse_re_stack_symbol_t symbol;
+  reg_errcode_t status = REG_OK;
+  tre_stack_t *stack = ctx->stack;
+  int bottom = tre_stack_num_objects(stack);
+  int depth = 0;
+
+  DPRINT(("tre_parse: parsing '%.*" STRF "', len = %d\n",
+         ctx->len, ctx->re, ctx->len));
+
+  if (!ctx->nofirstsub)
+    {
+      STACK_PUSH(stack, ctx->re);
+      STACK_PUSH(stack, ctx->submatch_id);
+      STACK_PUSH(stack, PARSE_MARK_FOR_SUBMATCH);
+      ctx->submatch_id++;
+    }
+  STACK_PUSH(stack, PARSE_RE);
+  ctx->re_start = ctx->re;
+  ctx->re_end = ctx->re + ctx->len;
+
+
+  /* The following is basically just a recursive descent parser.  I use
+     an explicit stack instead of recursive functions mostly because of
+     two reasons: compatibility with systems which have an overflowable
+     call stack, and efficiency (both in lines of code and speed).  */
+  while (tre_stack_num_objects(stack) > bottom && status == REG_OK)
+    {
+      if (status != REG_OK)
+       break;
+      symbol = (tre_parse_re_stack_symbol_t)tre_stack_pop(stack);
+      switch (symbol)
+       {
+       case PARSE_RE:
+         /* Parse a full regexp.  A regexp is one or more branches,
+            separated by the union operator `|'. */
+         if (ctx->cflags & REG_EXTENDED)
+           STACK_PUSHX(stack, PARSE_UNION);
+         STACK_PUSHX(stack, PARSE_BRANCH);
+         break;
+
+       case PARSE_BRANCH:
+         /* Parse a branch.  A branch is one or more pieces, concatenated.
+            A piece is an atom possibly followed by a postfix operator. */
+         STACK_PUSHX(stack, PARSE_CATENATION);
+         STACK_PUSHX(stack, PARSE_PIECE);
+         break;
+
+       case PARSE_PIECE:
+         /* Parse a piece.  A piece is an atom possibly followed by one
+            or more postfix operators. */
+         STACK_PUSHX(stack, PARSE_POSTFIX);
+         STACK_PUSHX(stack, PARSE_ATOM);
+         break;
+
+       case PARSE_CATENATION:
+         /* If the expression has not ended, parse another piece. */
+         {
+           tre_char_t c;
+           if (ctx->re >= ctx->re_end)
+             break;
+           c = *ctx->re;
+           if (ctx->cflags & REG_EXTENDED && c == '|')
+             break;
+           if ((ctx->cflags & REG_EXTENDED
+                && c == ')' && depth > 0)
+               || (!(ctx->cflags & REG_EXTENDED)
+                   && (c == '\\'
+                       && *(ctx->re + 1) == ')')))
+             {
+               if (!(ctx->cflags & REG_EXTENDED) && depth == 0)
+                 status = REG_EPAREN;
+               DPRINT(("tre_parse:       group end: '%.*" STRF "'\n",
+                       ctx->re_end - ctx->re, ctx->re));
+               depth--;
+               if (!(ctx->cflags & REG_EXTENDED))
+                 ctx->re += 2;
+               break;
+             }
+
+           /* Left associative concatenation. */
+           STACK_PUSHX(stack, PARSE_CATENATION);
+           STACK_PUSHX(stack, result);
+           STACK_PUSHX(stack, PARSE_POST_CATENATION);
+           STACK_PUSHX(stack, PARSE_PIECE);
+           break;
+         }
+
+       case PARSE_POST_CATENATION:
+         {
+           tre_ast_node_t *tree = tre_stack_pop(stack);
+           tre_ast_node_t *tmp_node;
+           tmp_node = tre_ast_new_catenation(ctx->mem, tree, result);
+           if (!tmp_node)
+             return REG_ESPACE;
+           result = tmp_node;
+           break;
+         }
+
+       case PARSE_UNION:
+         if (ctx->re >= ctx->re_end)
+           break;
+         switch (*ctx->re)
+           {
+           case '|':
+             DPRINT(("tre_parse:       union: '%.*" STRF "'\n",
+                     ctx->re_end - ctx->re, ctx->re));
+             STACK_PUSHX(stack, PARSE_UNION);
+             STACK_PUSHX(stack, result);
+             STACK_PUSHX(stack, PARSE_POST_UNION);
+             STACK_PUSHX(stack, PARSE_BRANCH);
+             ctx->re++;
+             break;
+
+           case ')':
+             ctx->re++;
+             break;
+
+           default:
+             break;
+           }
+         break;
+
+       case PARSE_POST_UNION:
+         {
+           tre_ast_node_t *tmp_node;
+           tre_ast_node_t *tree = tre_stack_pop(stack);
+           tmp_node = tre_ast_new_union(ctx->mem, tree, result);
+           if (!tmp_node)
+             return REG_ESPACE;
+           result = tmp_node;
+           break;
+         }
+
+       case PARSE_POSTFIX:
+         /* Parse postfix operators. */
+         if (ctx->re >= ctx->re_end)
+           break;
+         switch (*ctx->re)
+           {
+           case '+':
+           case '?':
+             if (!(ctx->cflags & REG_EXTENDED))
+               break;
+           case '*':
+             {
+               tre_ast_node_t *tmp_node;
+               int rep_min = 0;
+               int rep_max = -1;
+               if (*ctx->re == '+')
+                 rep_min = 1;
+               if (*ctx->re == '?')
+                 rep_max = 1;
+
+               ctx->re++;
+               tmp_node = tre_ast_new_iter(ctx->mem, result, rep_min, rep_max);
+               if (tmp_node == NULL)
+                 return REG_ESPACE;
+               result = tmp_node;
+               STACK_PUSHX(stack, PARSE_POSTFIX);
+               break;
+             }
+
+           case '\\':
+             /* "\{" is special without REG_EXTENDED */
+             if (!(ctx->cflags & REG_EXTENDED)
+                 && ctx->re + 1 < ctx->re_end
+                 && *(ctx->re + 1) == '{')
+               {
+                 ctx->re++;
+                 goto parse_brace;
+               }
+             else
+               break;
+
+           case '{':
+             /* "{" is literal without REG_EXTENDED */
+             if (!(ctx->cflags & REG_EXTENDED))
+               break;
+
+           parse_brace:
+             DPRINT(("tre_parse:       bound: '%.*" STRF "'\n",
+                     ctx->re_end - ctx->re, ctx->re));
+             ctx->re++;
+
+             status = tre_parse_bound(ctx, &result);
+             if (status != REG_OK)
+               return status;
+             STACK_PUSHX(stack, PARSE_POSTFIX);
+             break;
+           }
+         break;
+
+       case PARSE_ATOM:
+         /* Parse an atom.  An atom is a regular expression enclosed in `()',
+            an empty set of `()', a bracket expression, `.', `^', `$',
+            a `\' followed by a character, or a single character. */
+
+         /* End of regexp? (empty string). */
+         if (ctx->re >= ctx->re_end)
+           goto parse_literal;
+
+         switch (*ctx->re)
+           {
+           case '(':  /* parenthesized subexpression */
+
+             if (ctx->cflags & REG_EXTENDED
+                 || (ctx->re > ctx->re_start
+                     && *(ctx->re - 1) == '\\'))
+               {
+                 depth++;
+                   {
+                     DPRINT(("tre_parse: group begin: '%.*" STRF
+                             "', submatch %d\n",
+                             ctx->re_end - ctx->re, ctx->re,
+                             ctx->submatch_id));
+                     ctx->re++;
+                     /* First parse a whole RE, then mark the resulting tree
+                        for submatching. */
+                     STACK_PUSHX(stack, ctx->submatch_id);
+                     STACK_PUSHX(stack, PARSE_MARK_FOR_SUBMATCH);
+                     STACK_PUSHX(stack, PARSE_RE);
+                     ctx->submatch_id++;
+                   }
+               }
+             else
+               goto parse_literal;
+             break;
+
+           case ')':  /* end of current subexpression */
+             if ((ctx->cflags & REG_EXTENDED && depth > 0)
+                 || (ctx->re > ctx->re_start
+                     && *(ctx->re - 1) == '\\'))
+               {
+                 DPRINT(("tre_parse:       empty: '%.*" STRF "'\n",
+                         ctx->re_end - ctx->re, ctx->re));
+                 /* We were expecting an atom, but instead the current
+                    subexpression was closed.  POSIX leaves the meaning of
+                    this to be implementation-defined.  We interpret this as
+                    an empty expression (which matches an empty string).  */
+                 result = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1);
+                 if (result == NULL)
+                   return REG_ESPACE;
+                 if (!(ctx->cflags & REG_EXTENDED))
+                   ctx->re--;
+               }
+             else
+               goto parse_literal;
+             break;
+
+           case '[': /* bracket expression */
+             DPRINT(("tre_parse:     bracket: '%.*" STRF "'\n",
+                     ctx->re_end - ctx->re, ctx->re));
+             ctx->re++;
+             status = tre_parse_bracket(ctx, &result);
+             if (status != REG_OK)
+               return status;
+             break;
+
+           case '\\':
+             /* If this is "\(" or "\)" chew off the backslash and
+                try again. */
+             if (!(ctx->cflags & REG_EXTENDED)
+                 && ctx->re + 1 < ctx->re_end
+                 && (*(ctx->re + 1) == '('
+                     || *(ctx->re + 1) == ')'))
+               {
+                 ctx->re++;
+                 STACK_PUSHX(stack, PARSE_ATOM);
+                 break;
+               }
+
+             if (ctx->re + 1 >= ctx->re_end)
+               /* Trailing backslash. */
+               return REG_EESCAPE;
+
+             DPRINT(("tre_parse:  bleep: '%.*" STRF "'\n",
+                     ctx->re_end - ctx->re, ctx->re));
+             ctx->re++;
+             switch (*ctx->re)
+               {
+               default:
+                 if (!(ctx->cflags & REG_EXTENDED) && tre_isdigit(*ctx->re))
+                   {
+                     /* Back reference. */
+                     int val = *ctx->re - '0';
+                     DPRINT(("tre_parse:     backref: '%.*" STRF "'\n",
+                             ctx->re_end - ctx->re + 1, ctx->re - 1));
+                     result = tre_ast_new_literal(ctx->mem, BACKREF, val,
+                                                  ctx->position);
+                     if (result == NULL)
+                       return REG_ESPACE;
+                     ctx->position++;
+                     ctx->max_backref = MAX(val, ctx->max_backref);
+                     ctx->re++;
+                   }
+                 else
+                   {
+                     /* Escaped character. */
+                     DPRINT(("tre_parse:     escaped: '%.*" STRF "'\n",
+                             ctx->re_end - ctx->re + 1, ctx->re - 1));
+                     result = tre_ast_new_literal(ctx->mem, *ctx->re, *ctx->re,
+                                                  ctx->position);
+                     ctx->position++;
+                     ctx->re++;
+                   }
+                 break;
+               }
+             if (result == NULL)
+               return REG_ESPACE;
+             break;
+
+           case '.':    /* the any-symbol */
+             DPRINT(("tre_parse:         any: '%.*" STRF "'\n",
+                     ctx->re_end - ctx->re, ctx->re));
+             if (ctx->cflags & REG_NEWLINE)
+               {
+                 tre_ast_node_t *tmp1;
+                 tre_ast_node_t *tmp2;
+                 tmp1 = tre_ast_new_literal(ctx->mem, 0, '\n' - 1,
+                                            ctx->position);
+                 if (!tmp1)
+                   return REG_ESPACE;
+                 tmp2 = tre_ast_new_literal(ctx->mem, '\n' + 1, TRE_CHAR_MAX,
+                                            ctx->position + 1);
+                 if (!tmp2)
+                   return REG_ESPACE;
+                 result = tre_ast_new_union(ctx->mem, tmp1, tmp2);
+                 if (!result)
+                   return REG_ESPACE;
+                 ctx->position += 2;
+               }
+             else
+               {
+                 result = tre_ast_new_literal(ctx->mem, 0, TRE_CHAR_MAX,
+                                              ctx->position);
+                 if (!result)
+                   return REG_ESPACE;
+                 ctx->position++;
+               }
+             ctx->re++;
+             break;
+
+           case '^':    /* beginning of line assertion */
+             /* '^' has a special meaning everywhere in EREs, and in the
+                beginning of the RE and after \( is BREs. */
+             if (ctx->cflags & REG_EXTENDED
+                 || (ctx->re - 2 >= ctx->re_start
+                     && *(ctx->re - 2) == '\\'
+                     && *(ctx->re - 1) == '(')
+                 || ctx->re == ctx->re_start)
+               {
+                 DPRINT(("tre_parse:         BOL: '%.*" STRF "'\n",
+                         ctx->re_end - ctx->re, ctx->re));
+                 result = tre_ast_new_literal(ctx->mem, ASSERTION,
+                                              ASSERT_AT_BOL, -1);
+                 if (result == NULL)
+                   return REG_ESPACE;
+                 ctx->re++;
+               }
+             else
+               goto parse_literal;
+             break;
+
+           case '$':    /* end of line assertion. */
+             /* '$' is special everywhere in EREs, and in the end of the
+                string and before \) is BREs. */
+             if (ctx->cflags & REG_EXTENDED
+                 || (ctx->re + 2 < ctx->re_end
+                     && *(ctx->re + 1) == '\\'
+                     && *(ctx->re + 2) == ')')
+                 || ctx->re + 1 == ctx->re_end)
+               {
+                 DPRINT(("tre_parse:         EOL: '%.*" STRF "'\n",
+                         ctx->re_end - ctx->re, ctx->re));
+                 result = tre_ast_new_literal(ctx->mem, ASSERTION,
+                                              ASSERT_AT_EOL, -1);
+                 if (result == NULL)
+                   return REG_ESPACE;
+                 ctx->re++;
+               }
+             else
+               goto parse_literal;
+             break;
+
+           default:
+           parse_literal:
+
+             /* We are expecting an atom.  If the subexpression (or the whole
+                regexp ends here, we interpret it as an empty expression
+                (which matches an empty string).  */
+             if (
+                 (ctx->re >= ctx->re_end
+                  || *ctx->re == '*'
+                  || (ctx->cflags & REG_EXTENDED
+                      && (*ctx->re == '|'
+                          || *ctx->re == '{'
+                          || *ctx->re == '+'
+                          || *ctx->re == '?'))
+                  /* Test for "\)" in BRE mode. */
+                  || (!(ctx->cflags & REG_EXTENDED)
+                      && ctx->re + 1 < ctx->re_end
+                      && *ctx->re == '\\'
+                      && *(ctx->re + 1) == '{')))
+               {
+                 DPRINT(("tre_parse:       empty: '%.*" STRF "'\n",
+                         ctx->re_end - ctx->re, ctx->re));
+                 result = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1);
+                 if (!result)
+                   return REG_ESPACE;
+                 break;
+               }
+
+             DPRINT(("tre_parse:     literal: '%.*" STRF "'\n",
+                     ctx->re_end - ctx->re, ctx->re));
+             /* Note that we can't use an tre_isalpha() test here, since there
+                may be characters which are alphabetic but neither upper or
+                lower case. */
+             if (ctx->cflags & REG_ICASE
+                 && (tre_isupper(*ctx->re) || tre_islower(*ctx->re)))
+               {
+                 tre_ast_node_t *tmp1;
+                 tre_ast_node_t *tmp2;
+
+                 /* XXX - Can there be more than one opposite-case
+                    counterpoints for some character in some locale?  Or
+                    more than two characters which all should be regarded
+                    the same character if case is ignored?  If yes, there
+                    does not seem to be a portable way to detect it.  I guess
+                    that at least for multi-character collating elements there
+                    could be several opposite-case counterpoints, but they
+                    cannot be supported portably anyway. */
+                 tmp1 = tre_ast_new_literal(ctx->mem, tre_toupper(*ctx->re),
+                                            tre_toupper(*ctx->re),
+                                            ctx->position);
+                 if (!tmp1)
+                   return REG_ESPACE;
+                 tmp2 = tre_ast_new_literal(ctx->mem, tre_tolower(*ctx->re),
+                                            tre_tolower(*ctx->re),
+                                            ctx->position);
+                 if (!tmp2)
+                   return REG_ESPACE;
+                 result = tre_ast_new_union(ctx->mem, tmp1, tmp2);
+                 if (!result)
+                   return REG_ESPACE;
+               }
+             else
+               {
+                 result = tre_ast_new_literal(ctx->mem, *ctx->re, *ctx->re,
+                                              ctx->position);
+                 if (!result)
+                   return REG_ESPACE;
+               }
+             ctx->position++;
+             ctx->re++;
+             break;
+           }
+         break;
+
+       case PARSE_MARK_FOR_SUBMATCH:
+         {
+           int submatch_id = (int)tre_stack_pop(stack);
+
+           if (result->submatch_id >= 0)
+             {
+               tre_ast_node_t *n, *tmp_node;
+               n = tre_ast_new_literal(ctx->mem, EMPTY, -1, -1);
+               if (n == NULL)
+                 return REG_ESPACE;
+               tmp_node = tre_ast_new_catenation(ctx->mem, n, result);
+               if (tmp_node == NULL)
+                 return REG_ESPACE;
+               tmp_node->num_submatches = result->num_submatches;
+               result = tmp_node;
+             }
+           result->submatch_id = submatch_id;
+           result->num_submatches++;
+           break;
+         }
+
+       case PARSE_RESTORE_CFLAGS:
+         ctx->cflags = (int)tre_stack_pop(stack);
+         break;
+       }
+    }
+
+  /* Check for missing closing parentheses. */
+  if (depth > 0)
+    return REG_EPAREN;
+
+  if (status == REG_OK)
+    ctx->result = result;
+
+  return status;
+}
+
+
+/***********************************************************************
+ from tre-compile.c
+***********************************************************************/
+
+/*
+  Algorithms to setup tags so that submatch addressing can be done.
+*/
+
+
+/* Inserts a catenation node to the root of the tree given in `node'.
+   As the left child a new tag with number `tag_id' to `node' is added,
+   and the right child is the old root. */
+/*              OR                  */
+/* Inserts a catenation node to the root of the tree given in `node'.
+   As the right child a new tag with number `tag_id' to `node' is added,
+   and the left child is the old root. */
+static reg_errcode_t
+tre_add_tag(tre_mem_t mem, tre_ast_node_t *node, int tag_id, int right)
+{
+  tre_catenation_t *c;
+  tre_ast_node_t *child_tag, *child_old;
+
+  DPRINT(("add_tag_%s: tag %d\n", right ? "right" : "left", tag_id));
+
+  c = tre_mem_alloc(mem, sizeof(*c));
+  if (c == NULL)
+    return REG_ESPACE;
+  child_tag = tre_ast_new_literal(mem, TAG, tag_id, -1);
+  if (child_tag == NULL)
+    return REG_ESPACE;
+  child_old = tre_mem_alloc(mem, sizeof(tre_ast_node_t));
+  if (child_old == NULL)
+    return REG_ESPACE;
+
+  child_old->obj = node->obj;
+  child_old->type = node->type;
+  child_old->nullable = -1;
+  child_old->submatch_id = -1;
+  child_old->firstpos = NULL;
+  child_old->lastpos = NULL;
+  child_old->num_tags = 0;
+  node->obj = c;
+  node->type = CATENATION;
+
+  c->right = c->left = child_old;
+  if (right) c->right = child_tag;
+  else c->left = child_tag;
+
+  return REG_OK;
+}
+
+typedef enum {
+  ADDTAGS_RECURSE,
+  ADDTAGS_AFTER_ITERATION,
+  ADDTAGS_AFTER_UNION_LEFT,
+  ADDTAGS_AFTER_UNION_RIGHT,
+  ADDTAGS_AFTER_CAT_LEFT,
+  ADDTAGS_AFTER_CAT_RIGHT,
+  ADDTAGS_SET_SUBMATCH_END
+} tre_addtags_symbol_t;
+
+
+typedef struct {
+  int tag;
+  int next_tag;
+} tre_tag_states_t;
+
+/* Adds tags to appropriate locations in the parse tree in `tree', so that
+   subexpressions marked for submatch addressing can be traced. */
+static reg_errcode_t
+tre_add_tags(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *tree,
+            tre_tnfa_t *tnfa)
+{
+  reg_errcode_t status = REG_OK;
+  tre_addtags_symbol_t symbol;
+  tre_ast_node_t *node = tree; /* Tree node we are currently looking at. */
+  int bottom = tre_stack_num_objects(stack);
+  /* True for first pass (counting number of needed tags) */
+  int first_pass = (mem == NULL || tnfa == NULL);
+  int *regset, *orig_regset;
+  int num_tags = 0; /* Total number of tags. */
+  int tag = 0;     /* The tag that is to be added next. */
+  int next_tag = 1; /* Next tag to use after this one. */
+  int *parents;            /* Stack of submatches the current submatch is
+                      contained in. */
+  tre_tag_states_t *saved_states;
+
+  tre_tag_direction_t direction = TRE_TAG_MINIMIZE;
+  if (!first_pass)
+      tnfa->end_tag = 0;
+
+  regset = xmalloc(sizeof(*regset) * ((tnfa->num_submatches + 1) * 2));
+  if (regset == NULL)
+    return REG_ESPACE;
+  regset[0] = -1;
+  orig_regset = regset;
+
+  parents = xmalloc(sizeof(*parents) * (tnfa->num_submatches + 1));
+  if (parents == NULL)
+    {
+      xfree(regset);
+      return REG_ESPACE;
+    }
+  parents[0] = -1;
+
+  saved_states = xmalloc(sizeof(*saved_states) * (tnfa->num_submatches + 1));
+  if (saved_states == NULL)
+    {
+      xfree(regset);
+      xfree(parents);
+      return REG_ESPACE;
+    }
+  else
+    {
+      unsigned int i;
+      for (i = 0; i <= tnfa->num_submatches; i++)
+       saved_states[i].tag = -1;
+    }
+
+  STACK_PUSH(stack, node);
+  STACK_PUSH(stack, ADDTAGS_RECURSE);
+
+  while (tre_stack_num_objects(stack) > bottom)
+    {
+      if (status != REG_OK)
+       break;
+
+      symbol = (tre_addtags_symbol_t)tre_stack_pop(stack);
+      switch (symbol)
+       {
+
+       case ADDTAGS_SET_SUBMATCH_END:
+         {
+           int id = (int)tre_stack_pop(stack);
+           int i;
+
+           /* Add end of this submatch to regset. */
+           for (i = 0; regset[i] >= 0; i++);
+           regset[i] = id * 2 + 1;
+           regset[i + 1] = -1;
+
+           /* Pop this submatch from the parents stack. */
+           for (i = 0; parents[i] >= 0; i++);
+           parents[i - 1] = -1;
+           break;
+         }
+
+       case ADDTAGS_RECURSE:
+         node = tre_stack_pop(stack);
+
+         if (node->submatch_id >= 0)
+           {
+             int id = node->submatch_id;
+             int i;
+
+
+             /* Add start of this submatch to regset. */
+             for (i = 0; regset[i] >= 0; i++);
+             regset[i] = id * 2;
+             regset[i + 1] = -1;
+
+             if (!first_pass)
+               {
+                 for (i = 0; parents[i] >= 0; i++);
+                 tnfa->submatch_data[id].parents = NULL;
+                 if (i > 0)
+                   {
+                     int *p = xmalloc(sizeof(*p) * (i + 1));
+                     if (p == NULL)
+                       {
+                         status = REG_ESPACE;
+                         break;
+                       }
+                     assert(tnfa->submatch_data[id].parents == NULL);
+                     tnfa->submatch_data[id].parents = p;
+                     for (i = 0; parents[i] >= 0; i++)
+                       p[i] = parents[i];
+                     p[i] = -1;
+                   }
+               }
+
+             /* Add end of this submatch to regset after processing this
+                node. */
+             STACK_PUSHX(stack, node->submatch_id);
+             STACK_PUSHX(stack, ADDTAGS_SET_SUBMATCH_END);
+           }
+
+         switch (node->type)
+           {
+           case LITERAL:
+             {
+               tre_literal_t *lit = node->obj;
+
+               if (!IS_SPECIAL(lit) || IS_BACKREF(lit))
+                 {
+                   int i;
+                   DPRINT(("Literal %d-%d\n",
+                           (int)lit->code_min, (int)lit->code_max));
+                   if (regset[0] >= 0)
+                     {
+                       /* Regset is not empty, so add a tag before the
+                          literal or backref. */
+                       if (!first_pass)
+                         {
+                           status = tre_add_tag(mem, node, tag, 0 /*left*/);
+                           tnfa->tag_directions[tag] = direction;
+                           /* Go through the regset and set submatch data for
+                              submatches that are using this tag. */
+                           for (i = 0; regset[i] >= 0; i++)
+                             {
+                               int id = regset[i] >> 1;
+                               int start = !(regset[i] & 1);
+                               DPRINT(("  Using tag %d for %s offset of "
+                                       "submatch %d\n", tag,
+                                       start ? "start" : "end", id));
+                               if (start)
+                                 tnfa->submatch_data[id].so_tag = tag;
+                               else
+                                 tnfa->submatch_data[id].eo_tag = tag;
+                             }
+                         }
+                       else
+                         {
+                           DPRINT(("  num_tags = 1\n"));
+                           node->num_tags = 1;
+                         }
+
+                       DPRINT(("  num_tags++\n"));
+                       regset[0] = -1;
+                       tag = next_tag;
+                       num_tags++;
+                       next_tag++;
+                     }
+                 }
+               else
+                 {
+                   assert(!IS_TAG(lit));
+                 }
+               break;
+             }
+           case CATENATION:
+             {
+               tre_catenation_t *cat = node->obj;
+               tre_ast_node_t *left = cat->left;
+               tre_ast_node_t *right = cat->right;
+               int reserved_tag = -1;
+               DPRINT(("Catenation, next_tag = %d\n", next_tag));
+
+
+               /* After processing right child. */
+               STACK_PUSHX(stack, node);
+               STACK_PUSHX(stack, ADDTAGS_AFTER_CAT_RIGHT);
+
+               /* Process right child. */
+               STACK_PUSHX(stack, right);
+               STACK_PUSHX(stack, ADDTAGS_RECURSE);
+
+               /* After processing left child. */
+               STACK_PUSHX(stack, next_tag + left->num_tags);
+               DPRINT(("  Pushing %d for after left\n",
+                       next_tag + left->num_tags));
+               if (left->num_tags > 0 && right->num_tags > 0)
+                 {
+                   /* Reserve the next tag to the right child. */
+                   DPRINT(("  Reserving next_tag %d to right child\n",
+                           next_tag));
+                   reserved_tag = next_tag;
+                   next_tag++;
+                 }
+               STACK_PUSHX(stack, reserved_tag);
+               STACK_PUSHX(stack, ADDTAGS_AFTER_CAT_LEFT);
+
+               /* Process left child. */
+               STACK_PUSHX(stack, left);
+               STACK_PUSHX(stack, ADDTAGS_RECURSE);
+
+               }
+             break;
+           case ITERATION:
+             {
+               tre_iteration_t *iter = node->obj;
+               DPRINT(("Iteration\n"));
+
+               if (first_pass)
+                 {
+                   STACK_PUSHX(stack, regset[0] >= 0);
+                 }
+               else
+                 {
+                   STACK_PUSHX(stack, tag);
+                 }
+               STACK_PUSHX(stack, node);
+               STACK_PUSHX(stack, ADDTAGS_AFTER_ITERATION);
+
+               STACK_PUSHX(stack, iter->arg);
+               STACK_PUSHX(stack, ADDTAGS_RECURSE);
+
+               /* Regset is not empty, so add a tag here. */
+               if (regset[0] >= 0)
+                 {
+                   if (!first_pass)
+                     {
+                       int i;
+                       status = tre_add_tag(mem, node, tag, 0 /*left*/);
+                       tnfa->tag_directions[tag] = direction;
+                       /* Go through the regset and set submatch data for
+                          submatches that are using this tag. */
+                       for (i = 0; regset[i] >= 0; i++)
+                         {
+                           int id = regset[i] >> 1;
+                           int start = !(regset[i] & 1);
+                           DPRINT(("  Using tag %d for %s offset of "
+                                   "submatch %d\n", tag,
+                                   start ? "start" : "end", id));
+                           if (start)
+                             tnfa->submatch_data[id].so_tag = tag;
+                           else
+                             tnfa->submatch_data[id].eo_tag = tag;
+                         }
+                     }
+
+                   DPRINT(("  num_tags++\n"));
+                   regset[0] = -1;
+                   tag = next_tag;
+                   num_tags++;
+                   next_tag++;
+                 }
+               direction = TRE_TAG_MINIMIZE;
+             }
+             break;
+           case UNION:
+             {
+               tre_union_t *uni = node->obj;
+               tre_ast_node_t *left = uni->left;
+               tre_ast_node_t *right = uni->right;
+               int left_tag;
+               int right_tag;
+
+               if (regset[0] >= 0)
+                 {
+                   left_tag = next_tag;
+                   right_tag = next_tag + 1;
+                 }
+               else
+                 {
+                   left_tag = tag;
+                   right_tag = next_tag;
+                 }
+
+               DPRINT(("Union\n"));
+
+               /* After processing right child. */
+               STACK_PUSHX(stack, right_tag);
+               STACK_PUSHX(stack, left_tag);
+               STACK_PUSHX(stack, regset);
+               STACK_PUSHX(stack, regset[0] >= 0);
+               STACK_PUSHX(stack, node);
+               STACK_PUSHX(stack, right);
+               STACK_PUSHX(stack, left);
+               STACK_PUSHX(stack, ADDTAGS_AFTER_UNION_RIGHT);
+
+               /* Process right child. */
+               STACK_PUSHX(stack, right);
+               STACK_PUSHX(stack, ADDTAGS_RECURSE);
+
+               /* After processing left child. */
+               STACK_PUSHX(stack, ADDTAGS_AFTER_UNION_LEFT);
+
+               /* Process left child. */
+               STACK_PUSHX(stack, left);
+               STACK_PUSHX(stack, ADDTAGS_RECURSE);
+
+               /* Regset is not empty, so add a tag here. */
+               if (regset[0] >= 0)
+                 {
+                   if (!first_pass)
+                     {
+                       int i;
+                       status = tre_add_tag(mem, node, tag, 0 /*left*/);
+                       tnfa->tag_directions[tag] = direction;
+                       /* Go through the regset and set submatch data for
+                          submatches that are using this tag. */
+                       for (i = 0; regset[i] >= 0; i++)
+                         {
+                           int id = regset[i] >> 1;
+                           int start = !(regset[i] & 1);
+                           DPRINT(("  Using tag %d for %s offset of "
+                                   "submatch %d\n", tag,
+                                   start ? "start" : "end", id));
+                           if (start)
+                             tnfa->submatch_data[id].so_tag = tag;
+                           else
+                             tnfa->submatch_data[id].eo_tag = tag;
+                         }
+                     }
+
+                   DPRINT(("  num_tags++\n"));
+                   regset[0] = -1;
+                   tag = next_tag;
+                   num_tags++;
+                   next_tag++;
+                 }
+
+               if (node->num_submatches > 0)
+                 {
+                   /* The next two tags are reserved for markers. */
+                   next_tag++;
+                   tag = next_tag;
+                   next_tag++;
+                 }
+
+               break;
+             }
+           }
+
+         if (node->submatch_id >= 0)
+           {
+             int i;
+             /* Push this submatch on the parents stack. */
+             for (i = 0; parents[i] >= 0; i++);
+             parents[i] = node->submatch_id;
+             parents[i + 1] = -1;
+           }
+
+         break; /* end case: ADDTAGS_RECURSE */
+
+       case ADDTAGS_AFTER_ITERATION:
+         {
+           int enter_tag;
+           node = tre_stack_pop(stack);
+           if (first_pass)
+               node->num_tags = ((tre_iteration_t *)node->obj)->arg->num_tags
+                 + (int)tre_stack_pop(stack);
+           else
+               enter_tag = (int)tre_stack_pop(stack);
+
+           DPRINT(("After iteration\n"));
+           direction = TRE_TAG_MAXIMIZE;
+           break;
+         }
+
+       case ADDTAGS_AFTER_CAT_LEFT:
+         {
+           int new_tag = (int)tre_stack_pop(stack);
+           next_tag = (int)tre_stack_pop(stack);
+           DPRINT(("After cat left, tag = %d, next_tag = %d\n",
+                   tag, next_tag));
+           if (new_tag >= 0)
+             {
+               DPRINT(("  Setting tag to %d\n", new_tag));
+               tag = new_tag;
+             }
+           break;
+         }
+
+       case ADDTAGS_AFTER_CAT_RIGHT:
+         DPRINT(("After cat right\n"));
+         node = tre_stack_pop(stack);
+         if (first_pass)
+           node->num_tags = ((tre_catenation_t *)node->obj)->left->num_tags
+             + ((tre_catenation_t *)node->obj)->right->num_tags;
+         break;
+
+       case ADDTAGS_AFTER_UNION_LEFT:
+         DPRINT(("After union left\n"));
+         /* Lift the bottom of the `regset' array so that when processing
+            the right operand the items currently in the array are
+            invisible.  The original bottom was saved at ADDTAGS_UNION and
+            will be restored at ADDTAGS_AFTER_UNION_RIGHT below. */
+         while (*regset >= 0)
+           regset++;
+         break;
+
+       case ADDTAGS_AFTER_UNION_RIGHT:
+         {
+           int added_tags, tag_left, tag_right;
+           tre_ast_node_t *left = tre_stack_pop(stack);
+           tre_ast_node_t *right = tre_stack_pop(stack);
+           DPRINT(("After union right\n"));
+           node = tre_stack_pop(stack);
+           added_tags = (int)tre_stack_pop(stack);
+           if (first_pass)
+             {
+               node->num_tags = ((tre_union_t *)node->obj)->left->num_tags
+                 + ((tre_union_t *)node->obj)->right->num_tags + added_tags
+                 + ((node->num_submatches > 0) ? 2 : 0);
+             }
+           regset = tre_stack_pop(stack);
+           tag_left = (int)tre_stack_pop(stack);
+           tag_right = (int)tre_stack_pop(stack);
+
+           /* Add tags after both children, the left child gets a smaller
+              tag than the right child.  This guarantees that we prefer
+              the left child over the right child. */
+           /* XXX - This is not always necessary (if the children have
+              tags which must be seen for every match of that child). */
+           /* XXX - Check if this is the only place where tre_add_tag_right
+              is used.  If so, use tre_add_tag_left (putting the tag before
+              the child as opposed after the child) and throw away
+              tre_add_tag_right. */
+           if (node->num_submatches > 0)
+             {
+               if (!first_pass)
+                 {
+                   status = tre_add_tag(mem, left, tag_left, 1 /*right*/);
+                   tnfa->tag_directions[tag] = TRE_TAG_MAXIMIZE;
+                   status = tre_add_tag(mem, right, tag_right, 1 /*right*/);
+                   tnfa->tag_directions[tag] = TRE_TAG_MAXIMIZE;
+                 }
+               DPRINT(("  num_tags += 2\n"));
+               num_tags += 2;
+             }
+           direction = TRE_TAG_MAXIMIZE;
+           break;
+         }
+
+       default:
+         assert(0);
+         break;
+
+       } /* end switch(symbol) */
+    } /* end while(tre_stack_num_objects(stack) > bottom) */
+
+  if (!first_pass)
+    {
+      int i;
+      /* Go through the regset and set submatch data for
+        submatches that are using this tag. */
+      for (i = 0; regset[i] >= 0; i++)
+       {
+         int id = regset[i] >> 1;
+         int start = !(regset[i] & 1);
+         DPRINT(("  Using tag %d for %s offset of "
+                 "submatch %d\n", num_tags,
+                 start ? "start" : "end", id));
+         if (start)
+           tnfa->submatch_data[id].so_tag = num_tags;
+         else
+           tnfa->submatch_data[id].eo_tag = num_tags;
+       }
+    }
+
+  DPRINT(("tre_add_tags: %s complete.  Number of tags %d.\n",
+         first_pass? "First pass" : "Second pass", num_tags));
+
+  assert(tree->num_tags == num_tags);
+  tnfa->end_tag = num_tags;
+  tnfa->num_tags = num_tags;
+  xfree(orig_regset);
+  xfree(parents);
+  xfree(saved_states);
+  return status;
+}
+
+
+
+/*
+  AST to TNFA compilation routines.
+*/
+
+typedef enum {
+  COPY_RECURSE,
+  COPY_SET_RESULT_PTR
+} tre_copyast_symbol_t;
+
+/* Flags for tre_copy_ast(). */
+#define COPY_REMOVE_TAGS        1
+#define COPY_MAXIMIZE_FIRST_TAG         2
+
+static reg_errcode_t
+tre_copy_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
+            int flags, int *pos_add, tre_tag_direction_t *tag_directions,
+            tre_ast_node_t **copy, int *max_pos)
+{
+  reg_errcode_t status = REG_OK;
+  int bottom = tre_stack_num_objects(stack);
+  int num_copied = 0;
+  int first_tag = 1;
+  tre_ast_node_t **result = copy;
+  tre_copyast_symbol_t symbol;
+
+  STACK_PUSH(stack, ast);
+  STACK_PUSH(stack, COPY_RECURSE);
+
+  while (status == REG_OK && tre_stack_num_objects(stack) > bottom)
+    {
+      tre_ast_node_t *node;
+      if (status != REG_OK)
+       break;
+
+      symbol = (tre_copyast_symbol_t)tre_stack_pop(stack);
+      switch (symbol)
+       {
+       case COPY_SET_RESULT_PTR:
+         result = tre_stack_pop(stack);
+         break;
+       case COPY_RECURSE:
+         node = tre_stack_pop(stack);
+         switch (node->type)
+           {
+           case LITERAL:
+             {
+               tre_literal_t *lit = node->obj;
+               int pos = lit->position;
+               int min = lit->code_min;
+               int max = lit->code_max;
+               if (!IS_SPECIAL(lit) || IS_BACKREF(lit))
+                 {
+                   /* XXX - e.g. [ab] has only one position but two
+                      nodes, so we are creating holes in the state space
+                      here.  Not fatal, just wastes memory. */
+                   pos += *pos_add;
+                   num_copied++;
+                 }
+               else if (IS_TAG(lit) && (flags & COPY_REMOVE_TAGS))
+                 {
+                   /* Change this tag to empty. */
+                   min = EMPTY;
+                   max = pos = -1;
+                 }
+               else if (IS_TAG(lit) && (flags & COPY_MAXIMIZE_FIRST_TAG)
+                        && first_tag)
+                 {
+                   /* Maximize the first tag. */
+                   tag_directions[max] = TRE_TAG_MAXIMIZE;
+                   first_tag = 0;
+                 }
+               *result = tre_ast_new_literal(mem, min, max, pos);
+               if (*result == NULL)
+                 status = REG_ESPACE;
+
+               if (pos > *max_pos)
+                 *max_pos = pos;
+               break;
+             }
+           case UNION:
+             {
+               tre_union_t *uni = node->obj;
+               tre_union_t *copy;
+               *result = tre_ast_new_union(mem, uni->left, uni->right);
+               if (*result == NULL)
+                 {
+                   status = REG_ESPACE;
+                   break;
+                 }
+               copy = (*result)->obj;
+               result = &copy->left;
+               STACK_PUSHX(stack, uni->right);
+               STACK_PUSHX(stack, COPY_RECURSE);
+               STACK_PUSHX(stack, &copy->right);
+               STACK_PUSHX(stack, COPY_SET_RESULT_PTR);
+               STACK_PUSHX(stack, uni->left);
+               STACK_PUSHX(stack, COPY_RECURSE);
+               break;
+             }
+           case CATENATION:
+             {
+               tre_catenation_t *cat = node->obj;
+               tre_catenation_t *copy;
+               *result = tre_ast_new_catenation(mem, cat->left, cat->right);
+               if (*result == NULL)
+                 {
+                   status = REG_ESPACE;
+                   break;
+                 }
+               copy = (*result)->obj;
+               copy->left = NULL;
+               copy->right = NULL;
+               result = &copy->left;
+
+               STACK_PUSHX(stack, cat->right);
+               STACK_PUSHX(stack, COPY_RECURSE);
+               STACK_PUSHX(stack, &copy->right);
+               STACK_PUSHX(stack, COPY_SET_RESULT_PTR);
+               STACK_PUSHX(stack, cat->left);
+               STACK_PUSHX(stack, COPY_RECURSE);
+               break;
+             }
+           case ITERATION:
+             {
+               tre_iteration_t *iter = node->obj;
+               STACK_PUSHX(stack, iter->arg);
+               STACK_PUSHX(stack, COPY_RECURSE);
+               *result = tre_ast_new_iter(mem, iter->arg, iter->min, iter->max);
+               if (*result == NULL)
+                 {
+                   status = REG_ESPACE;
+                   break;
+                 }
+               iter = (*result)->obj;
+               result = &iter->arg;
+               break;
+             }
+           default:
+             assert(0);
+             break;
+           }
+         break;
+       }
+    }
+  *pos_add += num_copied;
+  return status;
+}
+
+typedef enum {
+  EXPAND_RECURSE,
+  EXPAND_AFTER_ITER
+} tre_expand_ast_symbol_t;
+
+/* Expands each iteration node that has a finite nonzero minimum or maximum
+   iteration count to a catenated sequence of copies of the node. */
+static reg_errcode_t
+tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
+              int *position, tre_tag_direction_t *tag_directions,
+              int *max_depth)
+{
+  reg_errcode_t status = REG_OK;
+  int bottom = tre_stack_num_objects(stack);
+  int pos_add = 0;
+  int pos_add_total = 0;
+  int max_pos = 0;
+  /* Approximate parameter nesting level. */
+  int iter_depth = 0;
+
+  STACK_PUSHR(stack, ast);
+  STACK_PUSHR(stack, EXPAND_RECURSE);
+  while (status == REG_OK && tre_stack_num_objects(stack) > bottom)
+    {
+      tre_ast_node_t *node;
+      tre_expand_ast_symbol_t symbol;
+
+      if (status != REG_OK)
+       break;
+
+      DPRINT(("pos_add %d\n", pos_add));
+
+      symbol = (tre_expand_ast_symbol_t)tre_stack_pop(stack);
+      node = tre_stack_pop(stack);
+      switch (symbol)
+       {
+       case EXPAND_RECURSE:
+         switch (node->type)
+           {
+           case LITERAL:
+             {
+               tre_literal_t *lit= node->obj;
+               if (!IS_SPECIAL(lit) || IS_BACKREF(lit))
+                 {
+                   lit->position += pos_add;
+                   if (lit->position > max_pos)
+                     max_pos = lit->position;
+                 }
+               break;
+             }
+           case UNION:
+             {
+               tre_union_t *uni = node->obj;
+               STACK_PUSHX(stack, uni->right);
+               STACK_PUSHX(stack, EXPAND_RECURSE);
+               STACK_PUSHX(stack, uni->left);
+               STACK_PUSHX(stack, EXPAND_RECURSE);
+               break;
+             }
+           case CATENATION:
+             {
+               tre_catenation_t *cat = node->obj;
+               STACK_PUSHX(stack, cat->right);
+               STACK_PUSHX(stack, EXPAND_RECURSE);
+               STACK_PUSHX(stack, cat->left);
+               STACK_PUSHX(stack, EXPAND_RECURSE);
+               break;
+             }
+           case ITERATION:
+             {
+               tre_iteration_t *iter = node->obj;
+               STACK_PUSHX(stack, pos_add);
+               STACK_PUSHX(stack, node);
+               STACK_PUSHX(stack, EXPAND_AFTER_ITER);
+               STACK_PUSHX(stack, iter->arg);
+               STACK_PUSHX(stack, EXPAND_RECURSE);
+               /* If we are going to expand this node at EXPAND_AFTER_ITER
+                  then don't increase the `pos' fields of the nodes now, it
+                  will get done when expanding. */
+               if (iter->min > 1 || iter->max > 1)
+                 pos_add = 0;
+               iter_depth++;
+               DPRINT(("iter\n"));
+               break;
+             }
+           default:
+             assert(0);
+             break;
+           }
+         break;
+       case EXPAND_AFTER_ITER:
+         {
+           tre_iteration_t *iter = node->obj;
+           int pos_add_last;
+           pos_add = (int)tre_stack_pop(stack);
+           pos_add_last = pos_add;
+           if (iter->min > 1 || iter->max > 1)
+             {
+               tre_ast_node_t *seq1 = NULL, *seq2 = NULL;
+               int i;
+               int pos_add_save = pos_add;
+
+               /* Create a catenated sequence of copies of the node. */
+               for (i = 0; i < iter->min; i++)
+                 {
+                   tre_ast_node_t *copy;
+                   /* Remove tags from all but the last copy. */
+                   int flags = ((i + 1 < iter->min)
+                                ? COPY_REMOVE_TAGS
+                                : COPY_MAXIMIZE_FIRST_TAG);
+                   DPRINT(("  pos_add %d\n", pos_add));
+                   pos_add_save = pos_add;
+                   status = tre_copy_ast(mem, stack, iter->arg, flags,
+                                         &pos_add, tag_directions, &copy,
+                                         &max_pos);
+                   if (status != REG_OK)
+                     return status;
+                   if (seq1 != NULL)
+                     seq1 = tre_ast_new_catenation(mem, seq1, copy);
+                   else
+                     seq1 = copy;
+                   if (seq1 == NULL)
+                     return REG_ESPACE;
+                 }
+
+               if (iter->max == -1)
+                 {
+                   /* No upper limit. */
+                   pos_add_save = pos_add;
+                   status = tre_copy_ast(mem, stack, iter->arg, 0,
+                                         &pos_add, NULL, &seq2, &max_pos);
+                   if (status != REG_OK)
+                     return status;
+                   seq2 = tre_ast_new_iter(mem, seq2, 0, -1);
+                   if (seq2 == NULL)
+                     return REG_ESPACE;
+                 }
+               else
+                 {
+                   for (i = iter->min; i < iter->max; i++)
+                     {
+                       tre_ast_node_t *tmp, *copy;
+                       pos_add_save = pos_add;
+                       status = tre_copy_ast(mem, stack, iter->arg, 0,
+                                             &pos_add, NULL, &copy, &max_pos);
+                       if (status != REG_OK)
+                         return status;
+                       if (seq2 != NULL)
+                         seq2 = tre_ast_new_catenation(mem, copy, seq2);
+                       else
+                         seq2 = copy;
+                       if (seq2 == NULL)
+                         return REG_ESPACE;
+                       tmp = tre_ast_new_literal(mem, EMPTY, -1, -1);
+                       if (tmp == NULL)
+                         return REG_ESPACE;
+                       seq2 = tre_ast_new_union(mem, tmp, seq2);
+                       if (seq2 == NULL)
+                         return REG_ESPACE;
+                     }
+                 }
+
+               pos_add = pos_add_save;
+               if (seq1 == NULL)
+                 seq1 = seq2;
+               else if (seq2 != NULL)
+                 seq1 = tre_ast_new_catenation(mem, seq1, seq2);
+               if (seq1 == NULL)
+                 return REG_ESPACE;
+               node->obj = seq1->obj;
+               node->type = seq1->type;
+             }
+
+           iter_depth--;
+           pos_add_total += pos_add - pos_add_last;
+           if (iter_depth == 0)
+             pos_add = pos_add_total;
+
+           break;
+         }
+       default:
+         assert(0);
+         break;
+       }
+    }
+
+  *position += pos_add_total;
+
+  /* `max_pos' should never be larger than `*position' if the above
+     code works, but just an extra safeguard let's make sure
+     `*position' is set large enough so enough memory will be
+     allocated for the transition table. */
+  if (max_pos > *position)
+    *position = max_pos;
+
+#ifdef TRE_DEBUG
+  DPRINT(("Expanded AST:\n"));
+  tre_ast_print(ast);
+  DPRINT(("*position %d, max_pos %d\n", *position, max_pos));
+#endif
+
+  return status;
+}
+
+static tre_pos_and_tags_t *
+tre_set_empty(tre_mem_t mem)
+{
+  tre_pos_and_tags_t *new_set;
+
+  new_set = tre_mem_calloc(mem, sizeof(*new_set));
+  if (new_set == NULL)
+    return NULL;
+
+  new_set[0].position = -1;
+  new_set[0].code_min = -1;
+  new_set[0].code_max = -1;
+
+  return new_set;
+}
+
+static tre_pos_and_tags_t *
+tre_set_one(tre_mem_t mem, int position, int code_min, int code_max,
+           tre_ctype_t class, tre_ctype_t *neg_classes, int backref)
+{
+  tre_pos_and_tags_t *new_set;
+
+  new_set = tre_mem_calloc(mem, sizeof(*new_set) * 2);
+  if (new_set == NULL)
+    return NULL;
+
+  new_set[0].position = position;
+  new_set[0].code_min = code_min;
+  new_set[0].code_max = code_max;
+  new_set[0].class = class;
+  new_set[0].neg_classes = neg_classes;
+  new_set[0].backref = backref;
+  new_set[1].position = -1;
+  new_set[1].code_min = -1;
+  new_set[1].code_max = -1;
+
+  return new_set;
+}
+
+static tre_pos_and_tags_t *
+tre_set_union(tre_mem_t mem, tre_pos_and_tags_t *set1, tre_pos_and_tags_t *set2,
+             int *tags, int assertions)
+{
+  int s1, s2, i, j;
+  tre_pos_and_tags_t *new_set;
+  int *new_tags;
+  int num_tags;
+
+  for (num_tags = 0; tags != NULL && tags[num_tags] >= 0; num_tags++);
+  for (s1 = 0; set1[s1].position >= 0; s1++);
+  for (s2 = 0; set2[s2].position >= 0; s2++);
+  new_set = tre_mem_calloc(mem, sizeof(*new_set) * (s1 + s2 + 1));
+  if (!new_set )
+    return NULL;
+
+  for (s1 = 0; set1[s1].position >= 0; s1++)
+    {
+      new_set[s1].position = set1[s1].position;
+      new_set[s1].code_min = set1[s1].code_min;
+      new_set[s1].code_max = set1[s1].code_max;
+      new_set[s1].assertions = set1[s1].assertions | assertions;
+      new_set[s1].class = set1[s1].class;
+      new_set[s1].neg_classes = set1[s1].neg_classes;
+      new_set[s1].backref = set1[s1].backref;
+      if (set1[s1].tags == NULL && tags == NULL)
+       new_set[s1].tags = NULL;
+      else
+       {
+         for (i = 0; set1[s1].tags != NULL && set1[s1].tags[i] >= 0; i++);
+         new_tags = tre_mem_alloc(mem, (sizeof(*new_tags)
+                                        * (i + num_tags + 1)));
+         if (new_tags == NULL)
+           return NULL;
+         for (j = 0; j < i; j++)
+           new_tags[j] = set1[s1].tags[j];
+         for (i = 0; i < num_tags; i++)
+           new_tags[j + i] = tags[i];
+         new_tags[j + i] = -1;
+         new_set[s1].tags = new_tags;
+       }
+    }
+
+  for (s2 = 0; set2[s2].position >= 0; s2++)
+    {
+      new_set[s1 + s2].position = set2[s2].position;
+      new_set[s1 + s2].code_min = set2[s2].code_min;
+      new_set[s1 + s2].code_max = set2[s2].code_max;
+      /* XXX - why not | assertions here as well? */
+      new_set[s1 + s2].assertions = set2[s2].assertions;
+      new_set[s1 + s2].class = set2[s2].class;
+      new_set[s1 + s2].neg_classes = set2[s2].neg_classes;
+      new_set[s1 + s2].backref = set2[s2].backref;
+      if (set2[s2].tags == NULL)
+       new_set[s1 + s2].tags = NULL;
+      else
+       {
+         for (i = 0; set2[s2].tags[i] >= 0; i++);
+         new_tags = tre_mem_alloc(mem, sizeof(*new_tags) * (i + 1));
+         if (new_tags == NULL)
+           return NULL;
+         for (j = 0; j < i; j++)
+           new_tags[j] = set2[s2].tags[j];
+         new_tags[j] = -1;
+         new_set[s1 + s2].tags = new_tags;
+       }
+    }
+  new_set[s1 + s2].position = -1;
+  return new_set;
+}
+
+/* Finds the empty path through `node' which is the one that should be
+   taken according to POSIX.2 rules, and adds the tags on that path to
+   `tags'.   `tags' may be NULL.  If `num_tags_seen' is not NULL, it is
+   set to the number of tags seen on the path. */
+static reg_errcode_t
+tre_match_empty(tre_stack_t *stack, tre_ast_node_t *node, int *tags,
+               int *assertions, int *num_tags_seen)
+{
+  tre_literal_t *lit;
+  tre_union_t *uni;
+  tre_catenation_t *cat;
+  tre_iteration_t *iter;
+  int i;
+  int bottom = tre_stack_num_objects(stack);
+  reg_errcode_t status = REG_OK;
+  if (num_tags_seen)
+    *num_tags_seen = 0;
+
+  status = tre_stack_push(stack, node);
+
+  /* Walk through the tree recursively. */
+  while (status == REG_OK && tre_stack_num_objects(stack) > bottom)
+    {
+      node = tre_stack_pop(stack);
+
+      switch (node->type)
+       {
+       case LITERAL:
+         lit = (tre_literal_t *)node->obj;
+         switch (lit->code_min)
+           {
+           case TAG:
+             if (lit->code_max >= 0)
+               {
+                 if (tags != NULL)
+                   {
+                     /* Add the tag to `tags'. */
+                     for (i = 0; tags[i] >= 0; i++)
+                       if (tags[i] == lit->code_max)
+                         break;
+                     if (tags[i] < 0)
+                       {
+                         tags[i] = lit->code_max;
+                         tags[i + 1] = -1;
+                       }
+                   }
+                 if (num_tags_seen)
+                   (*num_tags_seen)++;
+               }
+             break;
+           case ASSERTION:
+             assert(lit->code_max >= 1
+                    || lit->code_max <= ASSERT_LAST);
+             if (assertions != NULL)
+               *assertions |= lit->code_max;
+             break;
+           case EMPTY:
+             break;
+           default:
+             assert(0);
+             break;
+           }
+         break;
+
+       case UNION:
+         /* Subexpressions starting earlier take priority over ones
+            starting later, so we prefer the left subexpression over the
+            right subexpression. */
+         uni = (tre_union_t *)node->obj;
+         if (uni->left->nullable)
+           STACK_PUSHX(stack, uni->left)
+         else if (uni->right->nullable)
+           STACK_PUSHX(stack, uni->right)
+         else
+           assert(0);
+         break;
+
+       case CATENATION:
+         /* The path must go through both children. */
+         cat = (tre_catenation_t *)node->obj;
+         assert(cat->left->nullable);
+         assert(cat->right->nullable);
+         STACK_PUSHX(stack, cat->left);
+         STACK_PUSHX(stack, cat->right);
+         break;
+
+       case ITERATION:
+         /* A match with an empty string is preferred over no match at
+            all, so we go through the argument if possible. */
+         iter = (tre_iteration_t *)node->obj;
+         if (iter->arg->nullable)
+           STACK_PUSHX(stack, iter->arg);
+         break;
+
+       default:
+         assert(0);
+         break;
+       }
+    }
+
+  return status;
+}
+
+
+typedef enum {
+  NFL_RECURSE,
+  NFL_POST_UNION,
+  NFL_POST_CATENATION,
+  NFL_POST_ITERATION
+} tre_nfl_stack_symbol_t;
+
+
+/* Computes and fills in the fields `nullable', `firstpos', and `lastpos' for
+   the nodes of the AST `tree'. */
+static reg_errcode_t
+tre_compute_nfl(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *tree)
+{
+  int bottom = tre_stack_num_objects(stack);
+
+  STACK_PUSHR(stack, tree);
+  STACK_PUSHR(stack, NFL_RECURSE);
+
+  while (tre_stack_num_objects(stack) > bottom)
+    {
+      tre_nfl_stack_symbol_t symbol;
+      tre_ast_node_t *node;
+
+      symbol = (tre_nfl_stack_symbol_t) tre_stack_pop(stack);
+      node = tre_stack_pop(stack);
+      switch (symbol)
+       {
+       case NFL_RECURSE:
+         switch (node->type)
+           {
+           case LITERAL:
+             {
+               tre_literal_t *lit = (tre_literal_t *)node->obj;
+               if (IS_BACKREF(lit))
+                 {
+                   /* Back references: nullable = false, firstpos = {i},
+                      lastpos = {i}. */
+                   node->nullable = 0;
+                   node->firstpos = tre_set_one(mem, lit->position, 0,
+                                            TRE_CHAR_MAX, 0, NULL, -1);
+                   if (!node->firstpos)
+                     return REG_ESPACE;
+                   node->lastpos = tre_set_one(mem, lit->position, 0,
+                                               TRE_CHAR_MAX, 0, NULL,
+                                               lit->code_max);
+                   if (!node->lastpos)
+                     return REG_ESPACE;
+                 }
+               else if (lit->code_min < 0)
+                 {
+                   /* Tags, empty strings and zero width assertions:
+                      nullable = true, firstpos = {}, and lastpos = {}. */
+                   node->nullable = 1;
+                   node->firstpos = tre_set_empty(mem);
+                   if (!node->firstpos)
+                     return REG_ESPACE;
+                   node->lastpos = tre_set_empty(mem);
+                   if (!node->lastpos)
+                     return REG_ESPACE;
+                 }
+               else
+                 {
+                   /* Literal at position i: nullable = false, firstpos = {i},
+                      lastpos = {i}. */
+                   node->nullable = 0;
+                   node->firstpos =
+                     tre_set_one(mem, lit->position, lit->code_min,
+                                 lit->code_max, 0, NULL, -1);
+                   if (!node->firstpos)
+                     return REG_ESPACE;
+                   node->lastpos = tre_set_one(mem, lit->position,
+                                               lit->code_min, lit->code_max,
+                                               lit->class, lit->neg_classes,
+                                               -1);
+                   if (!node->lastpos)
+                     return REG_ESPACE;
+                 }
+               break;
+             }
+
+           case UNION:
+             /* Compute the attributes for the two subtrees, and after that
+                for this node. */
+             STACK_PUSHR(stack, node);
+             STACK_PUSHR(stack, NFL_POST_UNION);
+             STACK_PUSHR(stack, ((tre_union_t *)node->obj)->right);
+             STACK_PUSHR(stack, NFL_RECURSE);
+             STACK_PUSHR(stack, ((tre_union_t *)node->obj)->left);
+             STACK_PUSHR(stack, NFL_RECURSE);
+             break;
+
+           case CATENATION:
+             /* Compute the attributes for the two subtrees, and after that
+                for this node. */
+             STACK_PUSHR(stack, node);
+             STACK_PUSHR(stack, NFL_POST_CATENATION);
+             STACK_PUSHR(stack, ((tre_catenation_t *)node->obj)->right);
+             STACK_PUSHR(stack, NFL_RECURSE);
+             STACK_PUSHR(stack, ((tre_catenation_t *)node->obj)->left);
+             STACK_PUSHR(stack, NFL_RECURSE);
+             break;
+
+           case ITERATION:
+             /* Compute the attributes for the subtree, and after that for
+                this node. */
+             STACK_PUSHR(stack, node);
+             STACK_PUSHR(stack, NFL_POST_ITERATION);
+             STACK_PUSHR(stack, ((tre_iteration_t *)node->obj)->arg);
+             STACK_PUSHR(stack, NFL_RECURSE);
+             break;
+           }
+         break; /* end case: NFL_RECURSE */
+
+       case NFL_POST_UNION:
+         {
+           tre_union_t *uni = (tre_union_t *)node->obj;
+           node->nullable = uni->left->nullable || uni->right->nullable;
+           node->firstpos = tre_set_union(mem, uni->left->firstpos,
+                                          uni->right->firstpos, NULL, 0);
+           if (!node->firstpos)
+             return REG_ESPACE;
+           node->lastpos = tre_set_union(mem, uni->left->lastpos,
+                                         uni->right->lastpos, NULL, 0);
+           if (!node->lastpos)
+             return REG_ESPACE;
+           break;
+         }
+
+       case NFL_POST_ITERATION:
+         {
+           tre_iteration_t *iter = (tre_iteration_t *)node->obj;
+
+           if (iter->min == 0 || iter->arg->nullable)
+             node->nullable = 1;
+           else
+             node->nullable = 0;
+           node->firstpos = iter->arg->firstpos;
+           node->lastpos = iter->arg->lastpos;
+           break;
+         }
+
+       case NFL_POST_CATENATION:
+         {
+           int num_tags, *tags, assertions;
+           reg_errcode_t status;
+           tre_catenation_t *cat = node->obj;
+           node->nullable = cat->left->nullable && cat->right->nullable;
+
+           /* Compute firstpos. */
+           if (cat->left->nullable)
+             {
+               /* The left side matches the empty string.  Make a first pass
+                  with tre_match_empty() to get the number of tags. */
+               status = tre_match_empty(stack, cat->left,
+                                        NULL, NULL, &num_tags);
+               if (status != REG_OK)
+                 return status;
+               /* Allocate arrays for the tags and parameters. */
+               tags = xmalloc(sizeof(*tags) * (num_tags + 1));
+               if (!tags)
+                 return REG_ESPACE;
+               tags[0] = -1;
+               assertions = 0;
+               /* Second pass with tre_mach_empty() to get the list of
+                  tags. */
+               status = tre_match_empty(stack, cat->left, tags,
+                                        &assertions, NULL);
+               if (status != REG_OK)
+                 {
+                   xfree(tags);
+                   return status;
+                 }
+               node->firstpos =
+                 tre_set_union(mem, cat->right->firstpos, cat->left->firstpos,
+                               tags, assertions);
+               xfree(tags);
+               if (!node->firstpos)
+                 return REG_ESPACE;
+             }
+           else
+             {
+               node->firstpos = cat->left->firstpos;
+             }
+
+           /* Compute lastpos. */
+           if (cat->right->nullable)
+             {
+               /* The right side matches the empty string.  Make a first pass
+                  with tre_match_empty() to get the number of tags. */
+               status = tre_match_empty(stack, cat->right,
+                                        NULL, NULL, &num_tags);
+               if (status != REG_OK)
+                 return status;
+               /* Allocate arrays for the tags and parameters. */
+               tags = xmalloc(sizeof(int) * (num_tags + 1));
+               if (!tags)
+                 return REG_ESPACE;
+               tags[0] = -1;
+               assertions = 0;
+               /* Second pass with tre_mach_empty() to get the list of
+                  tags. */
+               status = tre_match_empty(stack, cat->right, tags,
+                                        &assertions, NULL);
+               if (status != REG_OK)
+                 {
+                   xfree(tags);
+                   return status;
+                 }
+               node->lastpos =
+                 tre_set_union(mem, cat->left->lastpos, cat->right->lastpos,
+                               tags, assertions);
+               xfree(tags);
+               if (!node->lastpos)
+                 return REG_ESPACE;
+             }
+           else
+             {
+               node->lastpos = cat->right->lastpos;
+             }
+           break;
+         }
+
+       default:
+         assert(0);
+         break;
+       }
+    }
+
+  return REG_OK;
+}
+
+
+/* Adds a transition from each position in `p1' to each position in `p2'. */
+static reg_errcode_t
+tre_make_trans(tre_pos_and_tags_t *p1, tre_pos_and_tags_t *p2,
+              tre_tnfa_transition_t *transitions,
+              int *counts, int *offs)
+{
+  tre_pos_and_tags_t *orig_p2 = p2;
+  tre_tnfa_transition_t *trans;
+  int i, j, k, l, dup, prev_p2_pos;
+
+  if (transitions != NULL)
+    while (p1->position >= 0)
+      {
+       p2 = orig_p2;
+       prev_p2_pos = -1;
+       while (p2->position >= 0)
+         {
+           /* Optimization: if this position was already handled, skip it. */
+           if (p2->position == prev_p2_pos)
+             {
+               p2++;
+               continue;
+             }
+           prev_p2_pos = p2->position;
+           /* Set `trans' to point to the next unused transition from
+              position `p1->position'. */
+           trans = transitions + offs[p1->position];
+           while (trans->state != NULL)
+             {
+#if 0
+               /* If we find a previous transition from `p1->position' to
+                  `p2->position', it is overwritten.  This can happen only
+                  if there are nested loops in the regexp, like in "((a)*)*".
+                  In POSIX.2 repetition using the outer loop is always
+                  preferred over using the inner loop.  Therefore the
+                  transition for the inner loop is useless and can be thrown
+                  away. */
+               /* XXX - The same position is used for all nodes in a bracket
+                  expression, so this optimization cannot be used (it will
+                  break bracket expressions) unless I figure out a way to
+                  detect it here. */
+               if (trans->state_id == p2->position)
+                 {
+                   DPRINT(("*"));
+                   break;
+                 }
+#endif
+               trans++;
+             }
+
+           if (trans->state == NULL)
+             (trans + 1)->state = NULL;
+           /* Use the character ranges, assertions, etc. from `p1' for
+              the transition from `p1' to `p2'. */
+           trans->code_min = p1->code_min;
+           trans->code_max = p1->code_max;
+           trans->state = transitions + offs[p2->position];
+           trans->state_id = p2->position;
+           trans->assertions = p1->assertions | p2->assertions
+             | (p1->class ? ASSERT_CHAR_CLASS : 0)
+             | (p1->neg_classes != NULL ? ASSERT_CHAR_CLASS_NEG : 0);
+           if (p1->backref >= 0)
+             {
+               assert((trans->assertions & ASSERT_CHAR_CLASS) == 0);
+               assert(p2->backref < 0);
+               trans->u.backref = p1->backref;
+               trans->assertions |= ASSERT_BACKREF;
+             }
+           else
+             trans->u.class = p1->class;
+           if (p1->neg_classes != NULL)
+             {
+               for (i = 0; p1->neg_classes[i] != (tre_ctype_t)0; i++);
+               trans->neg_classes =
+                 xmalloc(sizeof(*trans->neg_classes) * (i + 1));
+               if (trans->neg_classes == NULL)
+                 return REG_ESPACE;
+               for (i = 0; p1->neg_classes[i] != (tre_ctype_t)0; i++)
+                 trans->neg_classes[i] = p1->neg_classes[i];
+               trans->neg_classes[i] = (tre_ctype_t)0;
+             }
+           else
+             trans->neg_classes = NULL;
+
+           /* Find out how many tags this transition has. */
+           i = 0;
+           if (p1->tags != NULL)
+             while(p1->tags[i] >= 0)
+               i++;
+           j = 0;
+           if (p2->tags != NULL)
+             while(p2->tags[j] >= 0)
+               j++;
+
+           /* If we are overwriting a transition, free the old tag array. */
+           if (trans->tags != NULL)
+             xfree(trans->tags);
+           trans->tags = NULL;
+
+           /* If there were any tags, allocate an array and fill it. */
+           if (i + j > 0)
+             {
+               trans->tags = xmalloc(sizeof(*trans->tags) * (i + j + 1));
+               if (!trans->tags)
+                 return REG_ESPACE;
+               i = 0;
+               if (p1->tags != NULL)
+                 while(p1->tags[i] >= 0)
+                   {
+                     trans->tags[i] = p1->tags[i];
+                     i++;
+                   }
+               l = i;
+               j = 0;
+               if (p2->tags != NULL)
+                 while (p2->tags[j] >= 0)
+                   {
+                     /* Don't add duplicates. */
+                     dup = 0;
+                     for (k = 0; k < i; k++)
+                       if (trans->tags[k] == p2->tags[j])
+                         {
+                           dup = 1;
+                           break;
+                         }
+                     if (!dup)
+                       trans->tags[l++] = p2->tags[j];
+                     j++;
+                   }
+               trans->tags[l] = -1;
+             }
+
+
+#ifdef TRE_DEBUG
+           {
+             int *tags;
+
+             DPRINT(("  %2d -> %2d on %3d", p1->position, p2->position,
+                     p1->code_min));
+             if (p1->code_max != p1->code_min)
+               DPRINT(("-%3d", p1->code_max));
+             tags = trans->tags;
+             if (tags)
+               {
+                 DPRINT((", tags ["));
+                 while (*tags >= 0)
+                   {
+                     DPRINT(("%d", *tags));
+                     tags++;
+                     if (*tags >= 0)
+                       DPRINT((","));
+                   }
+                 DPRINT(("]"));
+               }
+             if (trans->assertions)
+               DPRINT((", assert %d", trans->assertions));
+             if (trans->assertions & ASSERT_BACKREF)
+               DPRINT((", backref %d", trans->u.backref));
+             else if (trans->class)
+               DPRINT((", class %ld", (long)trans->class));
+             if (trans->neg_classes)
+               DPRINT((", neg_classes %p", trans->neg_classes));
+             DPRINT(("\n"));
+           }
+#endif /* TRE_DEBUG */
+           p2++;
+         }
+       p1++;
+      }
+  else
+    /* Compute a maximum limit for the number of transitions leaving
+       from each state. */
+    while (p1->position >= 0)
+      {
+       p2 = orig_p2;
+       while (p2->position >= 0)
+         {
+           counts[p1->position]++;
+           p2++;
+         }
+       p1++;
+      }
+  return REG_OK;
+}
+
+/* Converts the syntax tree to a TNFA. All the transitions in the TNFA are
+   labelled with one character range (there are no transitions on empty
+   strings).  The TNFA takes O(n^2) space in the worst case, `n' is size of
+   the regexp. */
+static reg_errcode_t
+tre_ast_to_tnfa(tre_ast_node_t *node, tre_tnfa_transition_t *transitions,
+               int *counts, int *offs)
+{
+  tre_union_t *uni;
+  tre_catenation_t *cat;
+  tre_iteration_t *iter;
+  reg_errcode_t errcode = REG_OK;
+
+  /* XXX - recurse using a stack!. */
+  switch (node->type)
+    {
+    case LITERAL:
+      break;
+    case UNION:
+      uni = (tre_union_t *)node->obj;
+      errcode = tre_ast_to_tnfa(uni->left, transitions, counts, offs);
+      if (errcode != REG_OK)
+       return errcode;
+      errcode = tre_ast_to_tnfa(uni->right, transitions, counts, offs);
+      break;
+
+    case CATENATION:
+      cat = (tre_catenation_t *)node->obj;
+      /* Add a transition from each position in cat->left->lastpos
+        to each position in cat->right->firstpos. */
+      errcode = tre_make_trans(cat->left->lastpos, cat->right->firstpos,
+                              transitions, counts, offs);
+      if (errcode != REG_OK)
+       return errcode;
+      errcode = tre_ast_to_tnfa(cat->left, transitions, counts, offs);
+      if (errcode != REG_OK)
+       return errcode;
+      errcode = tre_ast_to_tnfa(cat->right, transitions, counts, offs);
+      break;
+
+    case ITERATION:
+      iter = (tre_iteration_t *)node->obj;
+      assert(iter->max == -1 || iter->max == 1);
+
+      if (iter->max == -1)
+       {
+         assert(iter->min == 0 || iter->min == 1);
+         /* Add a transition from each last position in the iterated
+            expression to each first position. */
+         errcode = tre_make_trans(iter->arg->lastpos, iter->arg->firstpos,
+                                  transitions, counts, offs);
+         if (errcode != REG_OK)
+           return errcode;
+       }
+      errcode = tre_ast_to_tnfa(iter->arg, transitions, counts, offs);
+      break;
+    }
+  return errcode;
+}
+
+
+static void
+tre_free(regex_t *preg)
+{
+  tre_tnfa_t *tnfa;
+  unsigned int i;
+  tre_tnfa_transition_t *trans;
+
+  tnfa = (void *)preg->TRE_REGEX_T_FIELD;
+  if (!tnfa)
+    return;
+
+  for (i = 0; i < tnfa->num_transitions; i++)
+    if (tnfa->transitions[i].state)
+      {
+       if (tnfa->transitions[i].tags)
+         xfree(tnfa->transitions[i].tags);
+       if (tnfa->transitions[i].neg_classes)
+         xfree(tnfa->transitions[i].neg_classes);
+      }
+  if (tnfa->transitions)
+    xfree(tnfa->transitions);
+
+  if (tnfa->initial)
+    {
+      for (trans = tnfa->initial; trans->state; trans++)
+       {
+         if (trans->tags)
+           xfree(trans->tags);
+       }
+      xfree(tnfa->initial);
+    }
+
+  if (tnfa->submatch_data)
+    {
+      for (i = 0; i < tnfa->num_submatches; i++)
+       if (tnfa->submatch_data[i].parents)
+         xfree(tnfa->submatch_data[i].parents);
+      xfree(tnfa->submatch_data);
+    }
+
+  if (tnfa->tag_directions)
+    xfree(tnfa->tag_directions);
+  xfree(tnfa);
+}
+
+
+#define ERROR_EXIT(err)                  \
+  do                             \
+    {                            \
+      errcode = err;             \
+      if (1) goto error_exit;    \
+    }                            \
+ while (0)
+
+
+static int
+tre_compile(regex_t *preg, const tre_char_t *regex, size_t n, int cflags)
+{
+  tre_stack_t *stack;
+  tre_ast_node_t *tree, *tmp_ast_l, *tmp_ast_r;
+  tre_pos_and_tags_t *p;
+  int *counts = NULL, *offs = NULL;
+  int i, add = 0;
+  tre_tnfa_transition_t *transitions, *initial;
+  tre_tnfa_t *tnfa = NULL;
+  tre_submatch_data_t *submatch_data;
+  tre_tag_direction_t *tag_directions = NULL;
+  reg_errcode_t errcode;
+  tre_mem_t mem;
+
+  /* Parse context. */
+  tre_parse_ctx_t parse_ctx;
+
+  /* Allocate a stack used throughout the compilation process for various
+     purposes. */
+  stack = tre_stack_new(512, 10240, 128);
+  if (!stack)
+    return REG_ESPACE;
+  /* Allocate a fast memory allocator. */
+  mem = tre_mem_new();
+  if (!mem)
+    {
+      tre_stack_destroy(stack);
+      return REG_ESPACE;
+    }
+
+  /* Parse the regexp. */
+  memset(&parse_ctx, 0, sizeof(parse_ctx));
+  parse_ctx.mem = mem;
+  parse_ctx.stack = stack;
+  parse_ctx.re = regex;
+  parse_ctx.len = n;
+  parse_ctx.cflags = cflags;
+  parse_ctx.max_backref = -1;
+  DPRINT(("tre_compile: parsing '%.*" STRF "'\n", n, regex));
+  errcode = tre_parse(&parse_ctx);
+  if (errcode != REG_OK)
+    ERROR_EXIT(errcode);
+  preg->re_nsub = parse_ctx.submatch_id - 1;
+  tree = parse_ctx.result;
+
+#ifdef TRE_DEBUG
+  tre_ast_print(tree);
+#endif /* TRE_DEBUG */
+
+  /* Referring to nonexistent subexpressions is illegal. */
+  if (parse_ctx.max_backref > (int)preg->re_nsub)
+    ERROR_EXIT(REG_ESUBREG);
+
+  /* Allocate the TNFA struct. */
+  tnfa = xcalloc(1, sizeof(tre_tnfa_t));
+  if (tnfa == NULL)
+    ERROR_EXIT(REG_ESPACE);
+  tnfa->have_backrefs = parse_ctx.max_backref >= 0;
+  tnfa->num_submatches = parse_ctx.submatch_id;
+
+  /* Set up tags for submatch addressing.  If REG_NOSUB is set and the
+     regexp does not have back references, this can be skipped. */
+  if (tnfa->have_backrefs || !(cflags & REG_NOSUB))
+    {
+      DPRINT(("tre_compile: setting up tags\n"));
+
+      /* Figure out how many tags we will need. */
+      errcode = tre_add_tags(NULL, stack, tree, tnfa);
+      if (errcode != REG_OK)
+       ERROR_EXIT(errcode);
+#ifdef TRE_DEBUG
+      tre_ast_print(tree);
+#endif /* TRE_DEBUG */
+
+      if (tnfa->num_tags > 0)
+       {
+         tag_directions = xmalloc(sizeof(*tag_directions)
+                                  * (tnfa->num_tags + 1));
+         if (tag_directions == NULL)
+           ERROR_EXIT(REG_ESPACE);
+         tnfa->tag_directions = tag_directions;
+         memset(tag_directions, -1,
+                sizeof(*tag_directions) * (tnfa->num_tags + 1));
+       }
+
+      submatch_data = xcalloc(parse_ctx.submatch_id, sizeof(*submatch_data));
+      if (submatch_data == NULL)
+       ERROR_EXIT(REG_ESPACE);
+      tnfa->submatch_data = submatch_data;
+
+      errcode = tre_add_tags(mem, stack, tree, tnfa);
+      if (errcode != REG_OK)
+       ERROR_EXIT(errcode);
+
+#ifdef TRE_DEBUG
+      for (i = 0; i < parse_ctx.submatch_id; i++)
+       DPRINT(("pmatch[%d] = {t%d, t%d}\n",
+               i, submatch_data[i].so_tag, submatch_data[i].eo_tag));
+      for (i = 0; i < tnfa->num_tags; i++)
+       DPRINT(("t%d is %s\n", i,
+               tag_directions[i] == TRE_TAG_MINIMIZE ?
+               "minimized" : "maximized"));
+#endif /* TRE_DEBUG */
+    }
+
+  /* Expand iteration nodes. */
+  errcode = tre_expand_ast(mem, stack, tree, &parse_ctx.position,
+                          tag_directions, NULL);
+  if (errcode != REG_OK)
+    ERROR_EXIT(errcode);
+
+  /* Add a dummy node for the final state.
+     XXX - For certain patterns this dummy node can be optimized away,
+          for example "a*" or "ab*".   Figure out a simple way to detect
+          this possibility. */
+  tmp_ast_l = tree;
+  tmp_ast_r = tre_ast_new_literal(mem, 0, 0, parse_ctx.position++);
+  if (tmp_ast_r == NULL)
+    ERROR_EXIT(REG_ESPACE);
+
+  tree = tre_ast_new_catenation(mem, tmp_ast_l, tmp_ast_r);
+  if (tree == NULL)
+    ERROR_EXIT(REG_ESPACE);
+
+#ifdef TRE_DEBUG
+  tre_ast_print(tree);
+  DPRINT(("Number of states: %d\n", parse_ctx.position));
+#endif /* TRE_DEBUG */
+
+  errcode = tre_compute_nfl(mem, stack, tree);
+  if (errcode != REG_OK)
+    ERROR_EXIT(errcode);
+
+  counts = xmalloc(sizeof(int) * parse_ctx.position);
+  if (counts == NULL)
+    ERROR_EXIT(REG_ESPACE);
+
+  offs = xmalloc(sizeof(int) * parse_ctx.position);
+  if (offs == NULL)
+    ERROR_EXIT(REG_ESPACE);
+
+  for (i = 0; i < parse_ctx.position; i++)
+    counts[i] = 0;
+  tre_ast_to_tnfa(tree, NULL, counts, NULL);
+
+  add = 0;
+  for (i = 0; i < parse_ctx.position; i++)
+    {
+      offs[i] = add;
+      add += counts[i] + 1;
+      counts[i] = 0;
+    }
+  transitions = xcalloc(add + 1, sizeof(*transitions));
+  if (transitions == NULL)
+    ERROR_EXIT(REG_ESPACE);
+  tnfa->transitions = transitions;
+  tnfa->num_transitions = add;
+
+  DPRINT(("Converting to TNFA:\n"));
+  errcode = tre_ast_to_tnfa(tree, transitions, counts, offs);
+  if (errcode != REG_OK)
+    ERROR_EXIT(errcode);
+
+  p = tree->firstpos;
+  i = 0;
+  while (p->position >= 0)
+    {
+      i++;
+
+#ifdef TRE_DEBUG
+      {
+       int *tags;
+       DPRINT(("initial: %d", p->position));
+       tags = p->tags;
+       if (tags != NULL)
+         {
+           if (*tags >= 0)
+             DPRINT(("/"));
+           while (*tags >= 0)
+             {
+               DPRINT(("%d", *tags));
+               tags++;
+               if (*tags >= 0)
+                 DPRINT((","));
+             }
+         }
+       DPRINT((", assert %d", p->assertions));
+       DPRINT(("\n"));
+      }
+#endif /* TRE_DEBUG */
+
+      p++;
+    }
+
+  initial = xcalloc(i + 1, sizeof(tre_tnfa_transition_t));
+  if (initial == NULL)
+    ERROR_EXIT(REG_ESPACE);
+  tnfa->initial = initial;
+
+  i = 0;
+  for (p = tree->firstpos; p->position >= 0; p++)
+    {
+      initial[i].state = transitions + offs[p->position];
+      initial[i].state_id = p->position;
+      initial[i].tags = NULL;
+      /* Copy the arrays p->tags, they are allocated
+        from a tre_mem object. */
+      if (p->tags)
+       {
+         int j;
+         for (j = 0; p->tags[j] >= 0; j++);
+         initial[i].tags = xmalloc(sizeof(*p->tags) * (j + 1));
+         if (!initial[i].tags)
+           ERROR_EXIT(REG_ESPACE);
+         memcpy(initial[i].tags, p->tags, sizeof(*p->tags) * (j + 1));
+       }
+      initial[i].assertions = p->assertions;
+      i++;
+    }
+  initial[i].state = NULL;
+
+  tnfa->num_transitions = add;
+  tnfa->final = transitions + offs[tree->lastpos[0].position];
+  tnfa->num_states = parse_ctx.position;
+  tnfa->cflags = cflags;
+
+  DPRINT(("final state %p\n", (void *)tnfa->final));
+
+  tre_mem_destroy(mem);
+  tre_stack_destroy(stack);
+  xfree(counts);
+  xfree(offs);
+
+  preg->TRE_REGEX_T_FIELD = (void *)tnfa;
+  return REG_OK;
+
+ error_exit:
+  /* Free everything that was allocated and return the error code. */
+  tre_mem_destroy(mem);
+  if (stack != NULL)
+    tre_stack_destroy(stack);
+  if (counts != NULL)
+    xfree(counts);
+  if (offs != NULL)
+    xfree(offs);
+  preg->TRE_REGEX_T_FIELD = (void *)tnfa;
+  tre_free(preg);
+  return errcode;
+}
+
+
+/***********************************************************************
+ from regcomp.c
+***********************************************************************/
+
+int
+regcomp(regex_t *preg, const char *regex, int cflags)
+{
+  int ret;
+  tre_char_t *wregex;
+  size_t n = strlen(regex);
+
+  if (n+1 > SIZE_MAX/sizeof(tre_char_t))
+    return REG_ESPACE;
+  wregex = xmalloc(sizeof(tre_char_t) * (n + 1));
+  if (wregex == NULL)
+    return REG_ESPACE;
+
+  n = mbstowcs(wregex, regex, n+1);
+  if (n == (size_t)-1) {
+    xfree(wregex);
+    return REG_BADPAT;
+  }
+
+  ret = tre_compile(preg, wregex, n, cflags);
+  xfree(wregex);
+
+  return ret;
+}
+
+void
+regfree(regex_t *preg)
+{
+  tre_free(preg);
+}
+
+/* EOF */
diff --git a/src/regex/regerror.c b/src/regex/regerror.c
new file mode 100644 (file)
index 0000000..39d70b2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+  regerror.c - POSIX regerror() implementation for TRE.
+
+  Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+#include <string.h>
+#include <regex.h>
+
+/* Error message strings for error codes listed in `regex.h'.  This list
+   needs to be in sync with the codes listed there, naturally. */
+
+/* Converted to single string by Rich Felker to remove the need for
+ * data relocations at runtime, 27 Feb 2006. */
+
+static const char tre_error_messages[] = {
+  "No error\0"
+  "No match\0"
+  "Invalid regexp\0"
+  "Unknown collating element\0"
+  "Unknown character class name\0"
+  "Trailing backslash\0"
+  "Invalid back reference\0"
+  "Missing ']'\0"
+  "Missing ')'\0"
+  "Missing '}'\0"
+  "Invalid contents of {}\0"
+  "Invalid character range\0"
+  "Out of memory\0"
+  "XXX\0"
+};
+
+size_t
+regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+  const char *err;
+  size_t err_len;
+
+  if (errcode >= 0 && errcode <= REG_BADRPT)
+    for (err=tre_error_messages; errcode; errcode--, err+=strlen(err)+1);
+  else
+    err = "Unknown error";
+
+  err_len = strlen(err) + 1;
+  if (errbuf_size > 0 && errbuf != NULL)
+    {
+      if (err_len > errbuf_size)
+       {
+         memcpy(errbuf, err, errbuf_size - 1);
+         errbuf[errbuf_size - 1] = '\0';
+       }
+      else
+       {
+         strcpy(errbuf, err);
+       }
+    }
+  return err_len;
+}
+
+/* EOF */
diff --git a/src/regex/regexec.c b/src/regex/regexec.c
new file mode 100644 (file)
index 0000000..0c3d283
--- /dev/null
@@ -0,0 +1,1107 @@
+/*
+  regexec.c - TRE POSIX compatible matching functions (and more).
+
+  Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <limits.h>
+
+#include <regex.h>
+
+#include "tre.h"
+
+#include <assert.h>
+
+static void
+tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
+               const tre_tnfa_t *tnfa, int *tags, int match_eo);
+
+/***********************************************************************
+ from tre-match-utils.h
+***********************************************************************/
+
+#define GET_NEXT_WCHAR() do {                                                 \
+    prev_c = next_c; pos += pos_add_next;                                     \
+    if ((pos_add_next = mbtowc(&next_c, str_byte, MB_LEN_MAX)) <= 0) {        \
+        if (pos_add_next < 0) return REG_NOMATCH;                             \
+        else pos_add_next++;                                                  \
+    }                                                                         \
+    str_byte += pos_add_next;                                                 \
+  } while (0)
+
+#define CHECK_ASSERTIONS(assertions)                                         \
+  (((assertions & ASSERT_AT_BOL)                                             \
+    && (pos > 0 || reg_notbol)                                               \
+    && (prev_c != L'\n' || !reg_newline))                                    \
+   || ((assertions & ASSERT_AT_EOL)                                          \
+       && (next_c != L'\0' || reg_noteol)                                    \
+       && (next_c != L'\n' || !reg_newline)))
+
+/* Returns 1 if `t1' wins `t2', 0 otherwise. */
+static int
+tre_tag_order(int num_tags, tre_tag_direction_t *tag_directions,
+             int *t1, int *t2)
+{
+  int i;
+  for (i = 0; i < num_tags; i++)
+    {
+      if (tag_directions[i] == TRE_TAG_MINIMIZE)
+       {
+         if (t1[i] < t2[i])
+           return 1;
+         if (t1[i] > t2[i])
+           return 0;
+       }
+      else
+       {
+         if (t1[i] > t2[i])
+           return 1;
+         if (t1[i] < t2[i])
+           return 0;
+       }
+    }
+  /*  assert(0);*/
+  return 0;
+}
+
+static int
+tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase)
+{
+  DPRINT(("neg_char_classes_test: %p, %d, %d\n", classes, wc, icase));
+  while (*classes != (tre_ctype_t)0)
+    if ((!icase && tre_isctype(wc, *classes))
+       || (icase && (tre_isctype(tre_toupper(wc), *classes)
+                     || tre_isctype(tre_tolower(wc), *classes))))
+      return 1; /* Match. */
+    else
+      classes++;
+  return 0; /* No match. */
+}
+
+
+/***********************************************************************
+ from tre-match-parallel.c
+***********************************************************************/
+
+/*
+  This algorithm searches for matches basically by reading characters
+  in the searched string one by one, starting at the beginning.         All
+  matching paths in the TNFA are traversed in parallel.         When two or
+  more paths reach the same state, exactly one is chosen according to
+  tag ordering rules; if returning submatches is not required it does
+  not matter which path is chosen.
+
+  The worst case time required for finding the leftmost and longest
+  match, or determining that there is no match, is always linearly
+  dependent on the length of the text being searched.
+
+  This algorithm cannot handle TNFAs with back referencing nodes.
+  See `tre-match-backtrack.c'.
+*/
+
+
+typedef struct {
+  tre_tnfa_transition_t *state;
+  int *tags;
+} tre_tnfa_reach_t;
+
+typedef struct {
+  int pos;
+  int **tags;
+} tre_reach_pos_t;
+
+
+#ifdef TRE_DEBUG
+static void
+tre_print_reach(const tre_tnfa_t *tnfa, tre_tnfa_reach_t *reach, int num_tags)
+{
+  int i;
+
+  while (reach->state != NULL)
+    {
+      DPRINT((" %p", (void *)reach->state));
+      if (num_tags > 0)
+       {
+         DPRINT(("/"));
+         for (i = 0; i < num_tags; i++)
+           {
+             DPRINT(("%d:%d", i, reach->tags[i]));
+             if (i < (num_tags-1))
+               DPRINT((","));
+           }
+       }
+      reach++;
+    }
+  DPRINT(("\n"));
+
+}
+#endif /* TRE_DEBUG */
+
+static reg_errcode_t
+tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len,
+                     int *match_tags, int eflags, int *match_end_ofs)
+{
+  /* State variables required by GET_NEXT_WCHAR. */
+  tre_char_t prev_c = 0, next_c = 0;
+  const char *str_byte = string;
+  int pos = -1;
+  int pos_add_next = 1;
+#ifdef TRE_MBSTATE
+  mbstate_t mbstate;
+#endif /* TRE_MBSTATE */
+  int reg_notbol = eflags & REG_NOTBOL;
+  int reg_noteol = eflags & REG_NOTEOL;
+  int reg_newline = tnfa->cflags & REG_NEWLINE;
+
+  char *buf;
+  tre_tnfa_transition_t *trans_i;
+  tre_tnfa_reach_t *reach, *reach_next, *reach_i, *reach_next_i;
+  tre_reach_pos_t *reach_pos;
+  int *tag_i;
+  int num_tags, i;
+
+  int match_eo = -1;      /* end offset of match (-1 if no match found yet) */
+  int new_match = 0;
+  int *tmp_tags = NULL;
+  int *tmp_iptr;
+
+#ifdef TRE_MBSTATE
+  memset(&mbstate, '\0', sizeof(mbstate));
+#endif /* TRE_MBSTATE */
+
+  if (!match_tags)
+    num_tags = 0;
+  else
+    num_tags = tnfa->num_tags;
+
+  /* Allocate memory for temporary data required for matching. This needs to
+     be done for every matching operation to be thread safe.  This allocates
+     everything in a single large block from the stack frame using alloca()
+     or with malloc() if alloca is unavailable. */
+  {
+    int tbytes, rbytes, pbytes, xbytes, total_bytes;
+    char *tmp_buf;
+    /* Compute the length of the block we need. */
+    tbytes = sizeof(*tmp_tags) * num_tags;
+    rbytes = sizeof(*reach_next) * (tnfa->num_states + 1);
+    pbytes = sizeof(*reach_pos) * tnfa->num_states;
+    xbytes = sizeof(int) * num_tags;
+    total_bytes =
+      (sizeof(long) - 1) * 4 /* for alignment paddings */
+      + (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes;
+
+    /* Allocate the memory. */
+#ifdef TRE_USE_ALLOCA
+    buf = alloca(total_bytes);
+#else /* !TRE_USE_ALLOCA */
+    buf = xmalloc(total_bytes);
+#endif /* !TRE_USE_ALLOCA */
+    if (buf == NULL)
+      return REG_ESPACE;
+    memset(buf, 0, total_bytes);
+
+    /* Get the various pointers within tmp_buf (properly aligned). */
+    tmp_tags = (void *)buf;
+    tmp_buf = buf + tbytes;
+    tmp_buf += ALIGN(tmp_buf, long);
+    reach_next = (void *)tmp_buf;
+    tmp_buf += rbytes;
+    tmp_buf += ALIGN(tmp_buf, long);
+    reach = (void *)tmp_buf;
+    tmp_buf += rbytes;
+    tmp_buf += ALIGN(tmp_buf, long);
+    reach_pos = (void *)tmp_buf;
+    tmp_buf += pbytes;
+    tmp_buf += ALIGN(tmp_buf, long);
+    for (i = 0; i < tnfa->num_states; i++)
+      {
+       reach[i].tags = (void *)tmp_buf;
+       tmp_buf += xbytes;
+       reach_next[i].tags = (void *)tmp_buf;
+       tmp_buf += xbytes;
+      }
+  }
+
+  for (i = 0; i < tnfa->num_states; i++)
+    reach_pos[i].pos = -1;
+
+  GET_NEXT_WCHAR();
+  pos = 0;
+
+  DPRINT(("length: %d\n", len));
+  DPRINT(("pos:chr/code | states and tags\n"));
+  DPRINT(("-------------+------------------------------------------------\n"));
+
+  reach_next_i = reach_next;
+  while (1)
+    {
+      /* If no match found yet, add the initial states to `reach_next'. */
+      if (match_eo < 0)
+       {
+         DPRINT((" init >"));
+         trans_i = tnfa->initial;
+         while (trans_i->state != NULL)
+           {
+             if (reach_pos[trans_i->state_id].pos < pos)
+               {
+                 if (trans_i->assertions
+                     && CHECK_ASSERTIONS(trans_i->assertions))
+                   {
+                     DPRINT(("assertion failed\n"));
+                     trans_i++;
+                     continue;
+                   }
+
+                 DPRINT((" %p", (void *)trans_i->state));
+                 reach_next_i->state = trans_i->state;
+                 for (i = 0; i < num_tags; i++)
+                   reach_next_i->tags[i] = -1;
+                 tag_i = trans_i->tags;
+                 if (tag_i)
+                   while (*tag_i >= 0)
+                     {
+                       if (*tag_i < num_tags)
+                         reach_next_i->tags[*tag_i] = pos;
+                       tag_i++;
+                     }
+                 if (reach_next_i->state == tnfa->final)
+                   {
+                     DPRINT(("  found empty match\n"));
+                     match_eo = pos;
+                     new_match = 1;
+                     for (i = 0; i < num_tags; i++)
+                       match_tags[i] = reach_next_i->tags[i];
+                   }
+                 reach_pos[trans_i->state_id].pos = pos;
+                 reach_pos[trans_i->state_id].tags = &reach_next_i->tags;
+                 reach_next_i++;
+               }
+             trans_i++;
+           }
+         DPRINT(("\n"));
+         reach_next_i->state = NULL;
+       }
+      else
+       {
+         if (num_tags == 0 || reach_next_i == reach_next)
+           /* We have found a match. */
+           break;
+       }
+
+      /* Check for end of string. */
+      if (!next_c) break;
+
+      GET_NEXT_WCHAR();
+
+#ifdef TRE_DEBUG
+      DPRINT(("%3d:%2lc/%05d |", pos - 1, (tre_cint_t)prev_c, (int)prev_c));
+      tre_print_reach(tnfa, reach_next, num_tags);
+      DPRINT(("%3d:%2lc/%05d |", pos, (tre_cint_t)next_c, (int)next_c));
+      tre_print_reach(tnfa, reach_next, num_tags);
+#endif /* TRE_DEBUG */
+
+      /* Swap `reach' and `reach_next'. */
+      reach_i = reach;
+      reach = reach_next;
+      reach_next = reach_i;
+
+      /* For each state in `reach' see if there is a transition leaving with
+        the current input symbol to a state not yet in `reach_next', and
+        add the destination states to `reach_next'. */
+      reach_next_i = reach_next;
+      for (reach_i = reach; reach_i->state; reach_i++)
+       {
+         for (trans_i = reach_i->state; trans_i->state; trans_i++)
+           {
+             /* Does this transition match the input symbol? */
+             if (trans_i->code_min <= prev_c &&
+                 trans_i->code_max >= prev_c)
+               {
+                 if (trans_i->assertions
+                     && (CHECK_ASSERTIONS(trans_i->assertions)
+                         /* Handle character class transitions. */
+                         || ((trans_i->assertions & ASSERT_CHAR_CLASS)
+                             && !(tnfa->cflags & REG_ICASE)
+                             && !tre_isctype((tre_cint_t)prev_c,
+                                             trans_i->u.class))
+                         || ((trans_i->assertions & ASSERT_CHAR_CLASS)
+                             && (tnfa->cflags & REG_ICASE)
+                             && (!tre_isctype(tre_tolower((tre_cint_t)prev_c),
+                                              trans_i->u.class)
+                                 && !tre_isctype(tre_toupper((tre_cint_t)prev_c),
+                                                 trans_i->u.class)))
+                         || ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG)
+                             && tre_neg_char_classes_match(trans_i->neg_classes,
+                                                           (tre_cint_t)prev_c,
+                                                           tnfa->cflags & REG_ICASE))))
+                   {
+                     DPRINT(("assertion failed\n"));
+                     continue;
+                   }
+
+                 /* Compute the tags after this transition. */
+                 for (i = 0; i < num_tags; i++)
+                   tmp_tags[i] = reach_i->tags[i];
+                 tag_i = trans_i->tags;
+                 if (tag_i != NULL)
+                   while (*tag_i >= 0)
+                     {
+                       if (*tag_i < num_tags)
+                         tmp_tags[*tag_i] = pos;
+                       tag_i++;
+                     }
+
+                 if (reach_pos[trans_i->state_id].pos < pos)
+                   {
+                     /* Found an unvisited node. */
+                     reach_next_i->state = trans_i->state;
+                     tmp_iptr = reach_next_i->tags;
+                     reach_next_i->tags = tmp_tags;
+                     tmp_tags = tmp_iptr;
+                     reach_pos[trans_i->state_id].pos = pos;
+                     reach_pos[trans_i->state_id].tags = &reach_next_i->tags;
+
+                     if (reach_next_i->state == tnfa->final
+                         && (match_eo == -1
+                             || (num_tags > 0
+                                 && reach_next_i->tags[0] <= match_tags[0])))
+                       {
+                         DPRINT(("  found match %p\n", trans_i->state));
+                         match_eo = pos;
+                         new_match = 1;
+                         for (i = 0; i < num_tags; i++)
+                           match_tags[i] = reach_next_i->tags[i];
+                       }
+                     reach_next_i++;
+
+                   }
+                 else
+                   {
+                     assert(reach_pos[trans_i->state_id].pos == pos);
+                     /* Another path has also reached this state.  We choose
+                        the winner by examining the tag values for both
+                        paths. */
+                     if (tre_tag_order(num_tags, tnfa->tag_directions,
+                                       tmp_tags,
+                                       *reach_pos[trans_i->state_id].tags))
+                       {
+                         /* The new path wins. */
+                         tmp_iptr = *reach_pos[trans_i->state_id].tags;
+                         *reach_pos[trans_i->state_id].tags = tmp_tags;
+                         if (trans_i->state == tnfa->final)
+                           {
+                             DPRINT(("  found better match\n"));
+                             match_eo = pos;
+                             new_match = 1;
+                             for (i = 0; i < num_tags; i++)
+                               match_tags[i] = tmp_tags[i];
+                           }
+                         tmp_tags = tmp_iptr;
+                       }
+                   }
+               }
+           }
+       }
+      reach_next_i->state = NULL;
+    }
+
+  DPRINT(("match end offset = %d\n", match_eo));
+
+#ifndef TRE_USE_ALLOCA
+  if (buf)
+    xfree(buf);
+#endif /* !TRE_USE_ALLOCA */
+
+  *match_end_ofs = match_eo;
+  return match_eo >= 0 ? REG_OK : REG_NOMATCH;
+}
+
+
+/***********************************************************************
+ from tre-match-backtrack.c
+***********************************************************************/
+
+/*
+  This matcher is for regexps that use back referencing.  Regexp matching
+  with back referencing is an NP-complete problem on the number of back
+  references.  The easiest way to match them is to use a backtracking
+  routine which basically goes through all possible paths in the TNFA
+  and chooses the one which results in the best (leftmost and longest)
+  match.  This can be spectacularly expensive and may run out of stack
+  space, but there really is no better known generic algorithm.         Quoting
+  Henry Spencer from comp.compilers:
+  <URL: http://compilers.iecc.com/comparch/article/93-03-102>
+
+    POSIX.2 REs require longest match, which is really exciting to
+    implement since the obsolete ("basic") variant also includes
+    \<digit>.  I haven't found a better way of tackling this than doing
+    a preliminary match using a DFA (or simulation) on a modified RE
+    that just replicates subREs for \<digit>, and then doing a
+    backtracking match to determine whether the subRE matches were
+    right.  This can be rather slow, but I console myself with the
+    thought that people who use \<digit> deserve very slow execution.
+    (Pun unintentional but very appropriate.)
+
+*/
+
+typedef struct {
+  int pos;
+  const char *str_byte;
+  tre_tnfa_transition_t *state;
+  int state_id;
+  int next_c;
+  int *tags;
+#ifdef TRE_MBSTATE
+  mbstate_t mbstate;
+#endif /* TRE_MBSTATE */
+} tre_backtrack_item_t;
+
+typedef struct tre_backtrack_struct {
+  tre_backtrack_item_t item;
+  struct tre_backtrack_struct *prev;
+  struct tre_backtrack_struct *next;
+} *tre_backtrack_t;
+
+#ifdef TRE_MBSTATE
+#define BT_STACK_MBSTATE_IN  stack->item.mbstate = (mbstate)
+#define BT_STACK_MBSTATE_OUT (mbstate) = stack->item.mbstate
+#else /* !TRE_MBSTATE */
+#define BT_STACK_MBSTATE_IN
+#define BT_STACK_MBSTATE_OUT
+#endif /* !TRE_MBSTATE */
+
+
+#ifdef TRE_USE_ALLOCA
+#define tre_bt_mem_new           tre_mem_newa
+#define tre_bt_mem_alloc         tre_mem_alloca
+#define tre_bt_mem_destroy(obj)          do { } while (0)
+#else /* !TRE_USE_ALLOCA */
+#define tre_bt_mem_new           tre_mem_new
+#define tre_bt_mem_alloc         tre_mem_alloc
+#define tre_bt_mem_destroy       tre_mem_destroy
+#endif /* !TRE_USE_ALLOCA */
+
+
+#define BT_STACK_PUSH(_pos, _str_byte, _str_wide, _state, _state_id, _next_c, _tags, _mbstate) \
+  do                                                                         \
+    {                                                                        \
+      int i;                                                                 \
+      if (!stack->next)                                                              \
+       {                                                                     \
+         tre_backtrack_t s;                                                  \
+         s = tre_bt_mem_alloc(mem, sizeof(*s));                              \
+         if (!s)                                                             \
+           {                                                                 \
+             tre_bt_mem_destroy(mem);                                        \
+             if (tags)                                                       \
+               xfree(tags);                                                  \
+             if (pmatch)                                                     \
+               xfree(pmatch);                                                \
+             if (states_seen)                                                \
+               xfree(states_seen);                                           \
+             return REG_ESPACE;                                              \
+           }                                                                 \
+         s->prev = stack;                                                    \
+         s->next = NULL;                                                     \
+         s->item.tags = tre_bt_mem_alloc(mem,                                \
+                                         sizeof(*tags) * tnfa->num_tags);    \
+         if (!s->item.tags)                                                  \
+           {                                                                 \
+             tre_bt_mem_destroy(mem);                                        \
+             if (tags)                                                       \
+               xfree(tags);                                                  \
+             if (pmatch)                                                     \
+               xfree(pmatch);                                                \
+             if (states_seen)                                                \
+               xfree(states_seen);                                           \
+             return REG_ESPACE;                                              \
+           }                                                                 \
+         stack->next = s;                                                    \
+         stack = s;                                                          \
+       }                                                                     \
+      else                                                                   \
+       stack = stack->next;                                                  \
+      stack->item.pos = (_pos);                                                      \
+      stack->item.str_byte = (_str_byte);                                    \
+      stack->item.state = (_state);                                          \
+      stack->item.state_id = (_state_id);                                    \
+      stack->item.next_c = (_next_c);                                        \
+      for (i = 0; i < tnfa->num_tags; i++)                                   \
+       stack->item.tags[i] = (_tags)[i];                                     \
+      BT_STACK_MBSTATE_IN;                                                   \
+    }                                                                        \
+  while (0)
+
+#define BT_STACK_POP()                                                       \
+  do                                                                         \
+    {                                                                        \
+      int i;                                                                 \
+      assert(stack->prev);                                                   \
+      pos = stack->item.pos;                                                 \
+      str_byte = stack->item.str_byte;                                       \
+      state = stack->item.state;                                             \
+      next_c = stack->item.next_c;                                           \
+      for (i = 0; i < tnfa->num_tags; i++)                                   \
+       tags[i] = stack->item.tags[i];                                        \
+      BT_STACK_MBSTATE_OUT;                                                  \
+      stack = stack->prev;                                                   \
+    }                                                                        \
+  while (0)
+
+#undef MIN
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+
+static reg_errcode_t
+tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
+                      int len, int *match_tags,
+                      int eflags, int *match_end_ofs)
+{
+  /* State variables required by GET_NEXT_WCHAR. */
+  tre_char_t prev_c = 0, next_c = 0;
+  const char *str_byte = string;
+  int pos = 0;
+  int pos_add_next = 1;
+#ifdef TRE_MBSTATE
+  mbstate_t mbstate;
+#endif /* TRE_MBSTATE */
+  int reg_notbol = eflags & REG_NOTBOL;
+  int reg_noteol = eflags & REG_NOTEOL;
+  int reg_newline = tnfa->cflags & REG_NEWLINE;
+
+  /* These are used to remember the necessary values of the above
+     variables to return to the position where the current search
+     started from. */
+  int next_c_start;
+  const char *str_byte_start;
+  int pos_start = -1;
+#ifdef TRE_MBSTATE
+  mbstate_t mbstate_start;
+#endif /* TRE_MBSTATE */
+
+  /* Compilation flags for this regexp. */
+  int cflags = tnfa->cflags;
+
+  /* End offset of best match so far, or -1 if no match found yet. */
+  int match_eo = -1;
+  /* Tag arrays. */
+  int *next_tags, *tags = NULL;
+  /* Current TNFA state. */
+  tre_tnfa_transition_t *state;
+  int *states_seen = NULL;
+
+  /* Memory allocator to for allocating the backtracking stack. */
+  tre_mem_t mem = tre_bt_mem_new();
+
+  /* The backtracking stack. */
+  tre_backtrack_t stack;
+
+  tre_tnfa_transition_t *trans_i;
+  regmatch_t *pmatch = NULL;
+  int ret;
+
+#ifdef TRE_MBSTATE
+  memset(&mbstate, '\0', sizeof(mbstate));
+#endif /* TRE_MBSTATE */
+
+  if (!mem)
+    return REG_ESPACE;
+  stack = tre_bt_mem_alloc(mem, sizeof(*stack));
+  if (!stack)
+    {
+      ret = REG_ESPACE;
+      goto error_exit;
+    }
+  stack->prev = NULL;
+  stack->next = NULL;
+
+#ifdef TRE_USE_ALLOCA
+  tags = alloca(sizeof(*tags) * tnfa->num_tags);
+  pmatch = alloca(sizeof(*pmatch) * tnfa->num_submatches);
+  states_seen = alloca(sizeof(*states_seen) * tnfa->num_states);
+#else /* !TRE_USE_ALLOCA */
+  tags = xmalloc(sizeof(*tags) * tnfa->num_tags);
+  if (!tags)
+    {
+      ret = REG_ESPACE;
+      goto error_exit;
+    }
+  pmatch = xmalloc(sizeof(*pmatch) * tnfa->num_submatches);
+  if (!pmatch)
+    {
+      ret = REG_ESPACE;
+      goto error_exit;
+    }
+  states_seen = xmalloc(sizeof(*states_seen) * tnfa->num_states);
+  if (!states_seen)
+    {
+      ret = REG_ESPACE;
+      goto error_exit;
+    }
+#endif /* !TRE_USE_ALLOCA */
+
+ retry:
+  {
+    int i;
+    for (i = 0; i < tnfa->num_tags; i++)
+      {
+       tags[i] = -1;
+       if (match_tags)
+         match_tags[i] = -1;
+      }
+    for (i = 0; i < tnfa->num_states; i++)
+      states_seen[i] = 0;
+  }
+
+  state = NULL;
+  pos = pos_start;
+  GET_NEXT_WCHAR();
+  pos_start = pos;
+  next_c_start = next_c;
+  str_byte_start = str_byte;
+#ifdef TRE_MBSTATE
+  mbstate_start = mbstate;
+#endif /* TRE_MBSTATE */
+
+  /* Handle initial states. */
+  next_tags = NULL;
+  for (trans_i = tnfa->initial; trans_i->state; trans_i++)
+    {
+      DPRINT(("> init %p, prev_c %lc\n", trans_i->state, (tre_cint_t)prev_c));
+      if (trans_i->assertions && CHECK_ASSERTIONS(trans_i->assertions))
+       {
+         DPRINT(("assert failed\n"));
+         continue;
+       }
+      if (state == NULL)
+       {
+         /* Start from this state. */
+         state = trans_i->state;
+         next_tags = trans_i->tags;
+       }
+      else
+       {
+         /* Backtrack to this state. */
+         DPRINT(("saving state %d for backtracking\n", trans_i->state_id));
+         BT_STACK_PUSH(pos, str_byte, str_wide, trans_i->state,
+                       trans_i->state_id, next_c, tags, mbstate);
+         {
+           int *tmp = trans_i->tags;
+           if (tmp)
+             while (*tmp >= 0)
+               stack->item.tags[*tmp++] = pos;
+         }
+       }
+    }
+
+  if (next_tags)
+    for (; *next_tags >= 0; next_tags++)
+      tags[*next_tags] = pos;
+
+
+  DPRINT(("entering match loop, pos %d, str_byte %p\n", pos, str_byte));
+  DPRINT(("pos:chr/code | state and tags\n"));
+  DPRINT(("-------------+------------------------------------------------\n"));
+
+  if (state == NULL)
+    goto backtrack;
+
+  while (1)
+    {
+      tre_tnfa_transition_t *trans_i, *next_state;
+      int empty_br_match;
+
+      DPRINT(("start loop\n"));
+      if (state == tnfa->final)
+       {
+         DPRINT(("  match found, %d %d\n", match_eo, pos));
+         if (match_eo < pos
+             || (match_eo == pos
+                 && match_tags
+                 && tre_tag_order(tnfa->num_tags, tnfa->tag_directions,
+                                  tags, match_tags)))
+           {
+             int i;
+             /* This match wins the previous match. */
+             DPRINT(("  win previous\n"));
+             match_eo = pos;
+             if (match_tags)
+               for (i = 0; i < tnfa->num_tags; i++)
+                 match_tags[i] = tags[i];
+           }
+         /* Our TNFAs never have transitions leaving from the final state,
+            so we jump right to backtracking. */
+         goto backtrack;
+       }
+
+#ifdef TRE_DEBUG
+      DPRINT(("%3d:%2lc/%05d | %p ", pos, (tre_cint_t)next_c, (int)next_c,
+             state));
+      {
+       int i;
+       for (i = 0; i < tnfa->num_tags; i++)
+         DPRINT(("%d%s", tags[i], i < tnfa->num_tags - 1 ? ", " : ""));
+       DPRINT(("\n"));
+      }
+#endif /* TRE_DEBUG */
+
+      /* Go to the next character in the input string. */
+      empty_br_match = 0;
+      trans_i = state;
+      if (trans_i->state && trans_i->assertions & ASSERT_BACKREF)
+       {
+         /* This is a back reference state.  All transitions leaving from
+            this state have the same back reference "assertion".  Instead
+            of reading the next character, we match the back reference. */
+         int so, eo, bt = trans_i->u.backref;
+         int bt_len;
+         int result;
+
+         DPRINT(("  should match back reference %d\n", bt));
+         /* Get the substring we need to match against.  Remember to
+            turn off REG_NOSUB temporarily. */
+         tre_fill_pmatch(bt + 1, pmatch, tnfa->cflags & !REG_NOSUB,
+                         tnfa, tags, pos);
+         so = pmatch[bt].rm_so;
+         eo = pmatch[bt].rm_eo;
+         bt_len = eo - so;
+
+         if (len < 0)
+           {
+             result = strncmp((char*)string + so, str_byte - 1, bt_len);
+           }
+         else if (len - pos < bt_len)
+           result = 1;
+         else
+           result = memcmp((char*)string + so, str_byte - 1, bt_len);
+
+         /* We can ignore multibyte characters here because the backref
+            string is already aligned at character boundaries. */
+         if (result == 0)
+           {
+             /* Back reference matched.  Check for infinite loop. */
+             if (bt_len == 0)
+               empty_br_match = 1;
+             if (empty_br_match && states_seen[trans_i->state_id])
+               {
+                 DPRINT(("  avoid loop\n"));
+                 goto backtrack;
+               }
+
+             states_seen[trans_i->state_id] = empty_br_match;
+
+             /* Advance in input string and resync `prev_c', `next_c'
+                and pos. */
+             DPRINT(("  back reference matched\n"));
+             str_byte += bt_len - 1;
+             pos += bt_len - 1;
+             GET_NEXT_WCHAR();
+             DPRINT(("  pos now %d\n", pos));
+           }
+         else
+           {
+             DPRINT(("  back reference did not match\n"));
+             goto backtrack;
+           }
+       }
+      else
+       {
+         /* Check for end of string. */
+         if (len < 0)
+           {
+             if (next_c == L'\0')
+               goto backtrack;
+           }
+         else
+           {
+             if (pos >= len)
+               goto backtrack;
+           }
+
+         /* Read the next character. */
+         GET_NEXT_WCHAR();
+       }
+
+      next_state = NULL;
+      for (trans_i = state; trans_i->state; trans_i++)
+       {
+         DPRINT(("  transition %d-%d (%c-%c) %d to %d\n",
+                 trans_i->code_min, trans_i->code_max,
+                 trans_i->code_min, trans_i->code_max,
+                 trans_i->assertions, trans_i->state_id));
+         if (trans_i->code_min <= prev_c && trans_i->code_max >= prev_c)
+           {
+             if (trans_i->assertions
+                 && (CHECK_ASSERTIONS(trans_i->assertions)
+                     /* Handle character class transitions. */
+                     || ((trans_i->assertions & ASSERT_CHAR_CLASS)
+                         && !(cflags & REG_ICASE)
+                         && !tre_isctype((tre_cint_t)prev_c, trans_i->u.class))
+                     || ((trans_i->assertions & ASSERT_CHAR_CLASS)
+                         && (cflags & REG_ICASE)
+                         && (!tre_isctype(tre_tolower((tre_cint_t)prev_c),
+                                          trans_i->u.class)
+                             && !tre_isctype(tre_toupper((tre_cint_t)prev_c),
+                                             trans_i->u.class)))
+                     || ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG)
+                         && tre_neg_char_classes_match(trans_i->neg_classes,
+                                                       (tre_cint_t)prev_c,
+                                                       cflags & REG_ICASE))))
+               {
+                 DPRINT(("  assertion failed\n"));
+                 continue;
+               }
+
+             if (next_state == NULL)
+               {
+                 /* First matching transition. */
+                 DPRINT(("  Next state is %d\n", trans_i->state_id));
+                 next_state = trans_i->state;
+                 next_tags = trans_i->tags;
+               }
+             else
+               {
+                 /* Second mathing transition.  We may need to backtrack here
+                    to take this transition instead of the first one, so we
+                    push this transition in the backtracking stack so we can
+                    jump back here if needed. */
+                 DPRINT(("  saving state %d for backtracking\n",
+                         trans_i->state_id));
+                 BT_STACK_PUSH(pos, str_byte, str_wide, trans_i->state,
+                               trans_i->state_id, next_c, tags, mbstate);
+                 {
+                   int *tmp;
+                   for (tmp = trans_i->tags; tmp && *tmp >= 0; tmp++)
+                     stack->item.tags[*tmp] = pos;
+                 }
+#if 0 /* XXX - it's important not to look at all transitions here to keep
+        the stack small! */
+                 break;
+#endif
+               }
+           }
+       }
+
+      if (next_state != NULL)
+       {
+         /* Matching transitions were found.  Take the first one. */
+         state = next_state;
+
+         /* Update the tag values. */
+         if (next_tags)
+           while (*next_tags >= 0)
+             tags[*next_tags++] = pos;
+       }
+      else
+       {
+       backtrack:
+         /* A matching transition was not found.  Try to backtrack. */
+         if (stack->prev)
+           {
+             DPRINT(("  backtracking\n"));
+             if (stack->item.state->assertions && ASSERT_BACKREF)
+               {
+                 DPRINT(("  states_seen[%d] = 0\n",
+                         stack->item.state_id));
+                 states_seen[stack->item.state_id] = 0;
+               }
+
+             BT_STACK_POP();
+           }
+         else if (match_eo < 0)
+           {
+             /* Try starting from a later position in the input string. */
+             /* Check for end of string. */
+             if (len < 0)
+               {
+                 if (next_c == L'\0')
+                   {
+                     DPRINT(("end of string.\n"));
+                     break;
+                   }
+               }
+             else
+               {
+                 if (pos >= len)
+                   {
+                     DPRINT(("end of string.\n"));
+                     break;
+                   }
+               }
+             DPRINT(("restarting from next start position\n"));
+             next_c = next_c_start;
+#ifdef TRE_MBSTATE
+             mbstate = mbstate_start;
+#endif /* TRE_MBSTATE */
+             str_byte = str_byte_start;
+             goto retry;
+           }
+         else
+           {
+             DPRINT(("finished\n"));
+             break;
+           }
+       }
+    }
+
+  ret = match_eo >= 0 ? REG_OK : REG_NOMATCH;
+  *match_end_ofs = match_eo;
+
+ error_exit:
+  tre_bt_mem_destroy(mem);
+#ifndef TRE_USE_ALLOCA
+  if (tags)
+    xfree(tags);
+  if (pmatch)
+    xfree(pmatch);
+  if (states_seen)
+    xfree(states_seen);
+#endif /* !TRE_USE_ALLOCA */
+
+  return ret;
+}
+
+
+/***********************************************************************
+ from regexec.c
+***********************************************************************/
+
+/* Fills the POSIX.2 regmatch_t array according to the TNFA tag and match
+   endpoint values. */
+static void
+tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
+               const tre_tnfa_t *tnfa, int *tags, int match_eo)
+{
+  tre_submatch_data_t *submatch_data;
+  unsigned int i, j;
+  int *parents;
+
+  i = 0;
+  if (match_eo >= 0 && !(cflags & REG_NOSUB))
+    {
+      /* Construct submatch offsets from the tags. */
+      DPRINT(("end tag = t%d = %d\n", tnfa->end_tag, match_eo));
+      submatch_data = tnfa->submatch_data;
+      while (i < tnfa->num_submatches && i < nmatch)
+       {
+         if (submatch_data[i].so_tag == tnfa->end_tag)
+           pmatch[i].rm_so = match_eo;
+         else
+           pmatch[i].rm_so = tags[submatch_data[i].so_tag];
+
+         if (submatch_data[i].eo_tag == tnfa->end_tag)
+           pmatch[i].rm_eo = match_eo;
+         else
+           pmatch[i].rm_eo = tags[submatch_data[i].eo_tag];
+
+         /* If either of the endpoints were not used, this submatch
+            was not part of the match. */
+         if (pmatch[i].rm_so == -1 || pmatch[i].rm_eo == -1)
+           pmatch[i].rm_so = pmatch[i].rm_eo = -1;
+
+         DPRINT(("pmatch[%d] = {t%d = %d, t%d = %d}\n", i,
+                 submatch_data[i].so_tag, pmatch[i].rm_so,
+                 submatch_data[i].eo_tag, pmatch[i].rm_eo));
+         i++;
+       }
+      /* Reset all submatches that are not within all of their parent
+        submatches. */
+      i = 0;
+      while (i < tnfa->num_submatches && i < nmatch)
+       {
+         if (pmatch[i].rm_eo == -1)
+           assert(pmatch[i].rm_so == -1);
+         assert(pmatch[i].rm_so <= pmatch[i].rm_eo);
+
+         parents = submatch_data[i].parents;
+         if (parents != NULL)
+           for (j = 0; parents[j] >= 0; j++)
+             {
+               DPRINT(("pmatch[%d] parent %d\n", i, parents[j]));
+               if (pmatch[i].rm_so < pmatch[parents[j]].rm_so
+                   || pmatch[i].rm_eo > pmatch[parents[j]].rm_eo)
+                 pmatch[i].rm_so = pmatch[i].rm_eo = -1;
+             }
+         i++;
+       }
+    }
+
+  while (i < nmatch)
+    {
+      pmatch[i].rm_so = -1;
+      pmatch[i].rm_eo = -1;
+      i++;
+    }
+}
+
+
+/*
+  Wrapper functions for POSIX compatible regexp matching.
+*/
+
+static int
+tre_match(const tre_tnfa_t *tnfa, const void *string, size_t len,
+         size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+  reg_errcode_t status;
+  int *tags = NULL, eo;
+  if (tnfa->num_tags > 0 && nmatch > 0)
+    {
+#ifdef TRE_USE_ALLOCA
+      tags = alloca(sizeof(*tags) * tnfa->num_tags);
+#else /* !TRE_USE_ALLOCA */
+      tags = xmalloc(sizeof(*tags) * tnfa->num_tags);
+#endif /* !TRE_USE_ALLOCA */
+      if (tags == NULL)
+       return REG_ESPACE;
+    }
+
+  /* Dispatch to the appropriate matcher. */
+  if (tnfa->have_backrefs)
+    {
+      /* The regex has back references, use the backtracking matcher. */
+      status = tre_tnfa_run_backtrack(tnfa, string, len, tags, eflags, &eo);
+    }
+  else
+    {
+      /* Exact matching, no back references, use the parallel matcher. */
+      status = tre_tnfa_run_parallel(tnfa, string, len, tags, eflags, &eo);
+    }
+
+  if (status == REG_OK)
+    /* A match was found, so fill the submatch registers. */
+    tre_fill_pmatch(nmatch, pmatch, tnfa->cflags, tnfa, tags, eo);
+#ifndef TRE_USE_ALLOCA
+  if (tags)
+    xfree(tags);
+#endif /* !TRE_USE_ALLOCA */
+  return status;
+}
+
+int
+regexec(const regex_t *preg, const char *str,
+       size_t nmatch, regmatch_t pmatch[], int eflags)
+{
+  return tre_match((void *)preg->TRE_REGEX_T_FIELD, str, -1,
+                   nmatch, pmatch, eflags);
+}
+
+/* EOF */
diff --git a/src/regex/tre-mem.c b/src/regex/tre-mem.c
new file mode 100644 (file)
index 0000000..d7bdd3d
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+  tre-mem.c - TRE memory allocator
+
+  Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+/*
+  This memory allocator is for allocating small memory blocks efficiently
+  in terms of memory overhead and execution speed.  The allocated blocks
+  cannot be freed individually, only all at once.  There can be multiple
+  allocators, though.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tre.h"
+
+
+/* Returns a new memory allocator or NULL if out of memory. */
+tre_mem_t
+tre_mem_new_impl(int provided, void *provided_block)
+{
+  tre_mem_t mem;
+  if (provided)
+    {
+      mem = provided_block;
+      memset(mem, 0, sizeof(*mem));
+    }
+  else
+    mem = xcalloc(1, sizeof(*mem));
+  if (mem == NULL)
+    return NULL;
+  return mem;
+}
+
+
+/* Frees the memory allocator and all memory allocated with it. */
+void
+tre_mem_destroy(tre_mem_t mem)
+{
+  tre_list_t *tmp, *l = mem->blocks;
+
+  while (l != NULL)
+    {
+      xfree(l->data);
+      tmp = l->next;
+      xfree(l);
+      l = tmp;
+    }
+  xfree(mem);
+}
+
+
+/* Allocates a block of `size' bytes from `mem'.  Returns a pointer to the
+   allocated block or NULL if an underlying malloc() failed. */
+void *
+tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
+                  int zero, size_t size)
+{
+  void *ptr;
+
+  if (mem->failed)
+    {
+      DPRINT(("tre_mem_alloc: oops, called after failure?!\n"));
+      return NULL;
+    }
+
+#ifdef MALLOC_DEBUGGING
+  if (!provided)
+    {
+      ptr = xmalloc(1);
+      if (ptr == NULL)
+       {
+         DPRINT(("tre_mem_alloc: xmalloc forced failure\n"));
+         mem->failed = 1;
+         return NULL;
+       }
+      xfree(ptr);
+    }
+#endif /* MALLOC_DEBUGGING */
+
+  if (mem->n < size)
+    {
+      /* We need more memory than is available in the current block.
+        Allocate a new block. */
+      tre_list_t *l;
+      if (provided)
+       {
+         DPRINT(("tre_mem_alloc: using provided block\n"));
+         if (provided_block == NULL)
+           {
+             DPRINT(("tre_mem_alloc: provided block was NULL\n"));
+             mem->failed = 1;
+             return NULL;
+           }
+         mem->ptr = provided_block;
+         mem->n = TRE_MEM_BLOCK_SIZE;
+       }
+      else
+       {
+         int block_size;
+         if (size * 8 > TRE_MEM_BLOCK_SIZE)
+           block_size = size * 8;
+         else
+           block_size = TRE_MEM_BLOCK_SIZE;
+         DPRINT(("tre_mem_alloc: allocating new %d byte block\n",
+                 block_size));
+         l = xmalloc(sizeof(*l));
+         if (l == NULL)
+           {
+             mem->failed = 1;
+             return NULL;
+           }
+         l->data = xmalloc(block_size);
+         if (l->data == NULL)
+           {
+             xfree(l);
+             mem->failed = 1;
+             return NULL;
+           }
+         l->next = NULL;
+         if (mem->current != NULL)
+           mem->current->next = l;
+         if (mem->blocks == NULL)
+           mem->blocks = l;
+         mem->current = l;
+         mem->ptr = l->data;
+         mem->n = block_size;
+       }
+    }
+
+  /* Make sure the next pointer will be aligned. */
+  size += ALIGN(mem->ptr + size, long);
+
+  /* Allocate from current block. */
+  ptr = mem->ptr;
+  mem->ptr += size;
+  mem->n -= size;
+
+  /* Set to zero if needed. */
+  if (zero)
+    memset(ptr, 0, size);
+
+  return ptr;
+}
+
+/* EOF */
diff --git a/src/regex/tre.h b/src/regex/tre.h
new file mode 100644 (file)
index 0000000..bfd171f
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+  tre-internal.h - TRE internal definitions
+
+  Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+#include <regex.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define TRE_MULTIBYTE 1
+#undef  TRE_MBSTATE
+#define TRE_WCHAR 1
+#define TRE_USE_SYSTEM_WCTYPE 1
+#define HAVE_WCSTOMBS 1
+#define TRE_MB_CUR_MAX MB_CUR_MAX
+
+#define NDEBUG
+
+#define TRE_REGEX_T_FIELD __opaque
+typedef int reg_errcode_t;
+
+typedef wchar_t tre_char_t;
+
+
+#ifdef TRE_DEBUG
+#include <stdio.h>
+#define DPRINT(msg) do {printf msg; fflush(stdout);} while(0)
+#else /* !TRE_DEBUG */
+#define DPRINT(msg) do { } while(0)
+#endif /* !TRE_DEBUG */
+
+#define elementsof(x)  ( sizeof(x) / sizeof(x[0]) )
+
+#if 1
+int __mbtowc(wchar_t *, const char *);
+#define tre_mbrtowc(pwc, s, n, ps) (__mbtowc((pwc), (s)))
+#else
+#define tre_mbrtowc(pwc, s, n, ps) (mbtowc((pwc), (s), (n)))
+#endif
+
+/* Wide characters. */
+typedef wint_t tre_cint_t;
+#define TRE_CHAR_MAX WCHAR_MAX
+
+#ifdef TRE_MULTIBYTE
+#define TRE_MB_CUR_MAX MB_CUR_MAX
+#else /* !TRE_MULTIBYTE */
+#define TRE_MB_CUR_MAX 1
+#endif /* !TRE_MULTIBYTE */
+
+#define tre_isalnum iswalnum
+#define tre_isalpha iswalpha
+#define tre_isblank iswblank
+#define tre_iscntrl iswcntrl
+#define tre_isdigit iswdigit
+#define tre_isgraph iswgraph
+#define tre_islower iswlower
+#define tre_isprint iswprint
+#define tre_ispunct iswpunct
+#define tre_isspace iswspace
+#define tre_isupper iswupper
+#define tre_isxdigit iswxdigit
+
+#define tre_tolower towlower
+#define tre_toupper towupper
+#define tre_strlen  wcslen
+
+/* Use system provided iswctype() and wctype(). */
+typedef wctype_t tre_ctype_t;
+#define tre_isctype iswctype
+#define tre_ctype   wctype
+
+/* Returns number of bytes to add to (char *)ptr to make it
+   properly aligned for the type. */
+#define ALIGN(ptr, type) \
+  ((((long)ptr) % sizeof(type)) \
+   ? (sizeof(type) - (((long)ptr) % sizeof(type))) \
+   : 0)
+
+#undef MAX
+#undef MIN
+#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
+#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
+
+/* Define STRF to the correct printf formatter for strings. */
+#define STRF "ls"
+
+/* TNFA transition type. A TNFA state is an array of transitions,
+   the terminator is a transition with NULL `state'. */
+typedef struct tnfa_transition tre_tnfa_transition_t;
+
+struct tnfa_transition {
+  /* Range of accepted characters. */
+  tre_cint_t code_min;
+  tre_cint_t code_max;
+  /* Pointer to the destination state. */
+  tre_tnfa_transition_t *state;
+  /* ID number of the destination state. */
+  int state_id;
+  /* -1 terminated array of tags (or NULL). */
+  int *tags;
+  /* Assertion bitmap. */
+  int assertions;
+  /* Assertion parameters. */
+  union {
+    /* Character class assertion. */
+    tre_ctype_t class;
+    /* Back reference assertion. */
+    int backref;
+  } u;
+  /* Negative character class assertions. */
+  tre_ctype_t *neg_classes;
+};
+
+
+/* Assertions. */
+#define ASSERT_AT_BOL            1   /* Beginning of line. */
+#define ASSERT_AT_EOL            2   /* End of line. */
+#define ASSERT_CHAR_CLASS        4   /* Character class in `class'. */
+#define ASSERT_CHAR_CLASS_NEG    8   /* Character classes in `neg_classes'. */
+#define ASSERT_AT_BOW           16   /* Beginning of word. */
+#define ASSERT_AT_EOW           32   /* End of word. */
+#define ASSERT_AT_WB            64   /* Word boundary. */
+#define ASSERT_AT_WB_NEG       128   /* Not a word boundary. */
+#define ASSERT_BACKREF         256   /* A back reference in `backref'. */
+#define ASSERT_LAST            256
+
+/* Tag directions. */
+typedef enum {
+  TRE_TAG_MINIMIZE = 0,
+  TRE_TAG_MAXIMIZE = 1
+} tre_tag_direction_t;
+
+/* Instructions to compute submatch register values from tag values
+   after a successful match.  */
+struct tre_submatch_data {
+  /* Tag that gives the value for rm_so (submatch start offset). */
+  int so_tag;
+  /* Tag that gives the value for rm_eo (submatch end offset). */
+  int eo_tag;
+  /* List of submatches this submatch is contained in. */
+  int *parents;
+};
+
+typedef struct tre_submatch_data tre_submatch_data_t;
+
+
+/* TNFA definition. */
+typedef struct tnfa tre_tnfa_t;
+
+struct tnfa {
+  tre_tnfa_transition_t *transitions;
+  unsigned int num_transitions;
+  tre_tnfa_transition_t *initial;
+  tre_tnfa_transition_t *final;
+  tre_submatch_data_t *submatch_data;
+  unsigned int num_submatches;
+  tre_tag_direction_t *tag_directions;
+  int num_tags;
+  int end_tag;
+  int num_states;
+  int cflags;
+  int have_backrefs;
+};
+
+#if 0
+static int
+tre_compile(regex_t *preg, const tre_char_t *regex, size_t n, int cflags);
+
+static void
+tre_free(regex_t *preg);
+
+static void
+tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
+               const tre_tnfa_t *tnfa, int *tags, int match_eo);
+
+static reg_errcode_t
+tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len,
+                     tre_str_type_t type, int *match_tags, int eflags,
+                     int *match_end_ofs);
+
+static reg_errcode_t
+tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len,
+                     tre_str_type_t type, int *match_tags, int eflags,
+                     int *match_end_ofs);
+
+static reg_errcode_t
+tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
+                      int len, tre_str_type_t type, int *match_tags,
+                      int eflags, int *match_end_ofs);
+#endif
+
+/* from tre-mem.h: */
+
+#define TRE_MEM_BLOCK_SIZE 1024
+
+typedef struct tre_list {
+  void *data;
+  struct tre_list *next;
+} tre_list_t;
+
+typedef struct tre_mem_struct {
+  tre_list_t *blocks;
+  tre_list_t *current;
+  char *ptr;
+  size_t n;
+  int failed;
+  void **provided;
+} *tre_mem_t;
+
+#define tre_mem_new_impl   __tre_mem_new_impl
+#define tre_mem_alloc_impl __tre_mem_alloc_impl
+#define tre_mem_destroy    __tre_mem_destroy
+
+tre_mem_t tre_mem_new_impl(int provided, void *provided_block);
+void *tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
+                        int zero, size_t size);
+
+/* Returns a new memory allocator or NULL if out of memory. */
+#define tre_mem_new()  tre_mem_new_impl(0, NULL)
+
+/* Allocates a block of `size' bytes from `mem'.  Returns a pointer to the
+   allocated block or NULL if an underlying malloc() failed. */
+#define tre_mem_alloc(mem, size) tre_mem_alloc_impl(mem, 0, NULL, 0, size)
+
+/* Allocates a block of `size' bytes from `mem'.  Returns a pointer to the
+   allocated block or NULL if an underlying malloc() failed.  The memory
+   is set to zero. */
+#define tre_mem_calloc(mem, size) tre_mem_alloc_impl(mem, 0, NULL, 1, size)
+
+#ifdef TRE_USE_ALLOCA
+/* alloca() versions.  Like above, but memory is allocated with alloca()
+   instead of malloc(). */
+
+#define tre_mem_newa() \
+  tre_mem_new_impl(1, alloca(sizeof(struct tre_mem_struct)))
+
+#define tre_mem_alloca(mem, size)                                            \
+  ((mem)->n >= (size)                                                        \
+   ? tre_mem_alloc_impl((mem), 1, NULL, 0, (size))                           \
+   : tre_mem_alloc_impl((mem), 1, alloca(TRE_MEM_BLOCK_SIZE), 0, (size)))
+#endif /* TRE_USE_ALLOCA */
+
+
+/* Frees the memory allocator and all memory allocated with it. */
+void tre_mem_destroy(tre_mem_t mem);
+
+#define xmalloc malloc
+#define xcalloc calloc
+#define xfree free
+#define xrealloc realloc
+
+/* EOF */
diff --git a/src/select/poll.c b/src/select/poll.c
new file mode 100644 (file)
index 0000000..e92943e
--- /dev/null
@@ -0,0 +1,12 @@
+#include <poll.h>
+#include "syscall.h"
+#include "libc.h"
+
+int poll(struct pollfd *fds, nfds_t n, int timeout)
+{
+       int r;
+       CANCELPT_BEGIN;
+       r = syscall3(__NR_poll, (long)fds, n, timeout);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/select/pselect.c b/src/select/pselect.c
new file mode 100644 (file)
index 0000000..795c5b0
--- /dev/null
@@ -0,0 +1,15 @@
+#include <sys/select.h>
+#include "syscall.h"
+#include "libc.h"
+
+int pselect(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *ts, const sigset_t *mask)
+{
+       int r;
+       long data[2] = { (long)mask, 8 };
+       struct timespec ts_tmp;
+       if (ts) ts_tmp = *ts;
+       CANCELPT_BEGIN;
+       r = syscall6(__NR_pselect6, n, (long)rfds, (long)wfds, (long)efds, ts ? (long)&ts_tmp : 0, (long)data);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/select/select.c b/src/select/select.c
new file mode 100644 (file)
index 0000000..a604d09
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/select.h>
+#include "syscall.h"
+#include "libc.h"
+
+int select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+       int r;
+       CANCELPT_BEGIN;
+       r = syscall5(__NR__newselect, n, (long)rfds, (long)wfds, (long)efds, (long)tv);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/setjmp/i386/longjmp.s b/src/setjmp/i386/longjmp.s
new file mode 100644 (file)
index 0000000..c1a956c
--- /dev/null
@@ -0,0 +1,22 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,%function
+.type longjmp,%function
+_longjmp:
+longjmp:
+       movl  4(%esp),%edx
+       movl  8(%esp),%eax
+       testl    %eax,%eax
+       jnz .L0
+       incl     %eax
+.L0:
+       movl   (%edx),%ebx
+       movl  4(%edx),%esi
+       movl  8(%edx),%edi
+       movl 12(%edx),%ebp
+       movl 16(%edx),%ecx
+       movl     %ecx,%esp
+       movl 20(%edx),%ecx
+       jmp *%ecx
+.size _longjmp,.-_longjmp
+.size longjmp,.-longjmp
diff --git a/src/setjmp/i386/setjmp.s b/src/setjmp/i386/setjmp.s
new file mode 100644 (file)
index 0000000..6c078b1
--- /dev/null
@@ -0,0 +1,23 @@
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,%function
+.type _setjmp,%function
+.type setjmp,%function
+__setjmp:
+_setjmp:
+setjmp:
+       movl 4(%esp), %eax
+       movl    %ebx, (%eax)
+       movl    %esi, 4(%eax)
+       movl    %edi, 8(%eax)
+       movl    %ebp, 12(%eax)
+       leal 4(%esp), %ecx
+       movl    %ecx, 16(%eax)
+       movl  (%esp), %ecx
+       movl    %ecx, 20(%eax)
+       xorl    %eax, %eax
+       ret
+.size __setjmp,.-__setjmp
+.size _setjmp,.-_setjmp
+.size setjmp,.-setjmp
diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/setjmp/setjmp.c b/src/setjmp/setjmp.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/signal/bsd_signal.c b/src/signal/bsd_signal.c
new file mode 100644 (file)
index 0000000..0b9a685
--- /dev/null
@@ -0,0 +1,6 @@
+#include <signal.h>
+
+void (*bsd_signal(int sig, void (*func)(int)))(int)
+{
+       return signal(sig, func);
+}
diff --git a/src/signal/getitimer.c b/src/signal/getitimer.c
new file mode 100644 (file)
index 0000000..222d113
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/time.h>
+#include "syscall.h"
+
+int getitimer(int which, struct itimerval *old)
+{
+       int ret;
+       long kold[4];
+
+       if (!(ret = syscall2(__NR_getitimer, which, (long)&kold)))
+               *old = (struct itimerval){ { kold[0], kold[1] }, { kold[2], kold[3] } };
+       return ret;
+}
diff --git a/src/signal/i386/sigsetjmp.s b/src/signal/i386/sigsetjmp.s
new file mode 100644 (file)
index 0000000..0e7eefb
--- /dev/null
@@ -0,0 +1,13 @@
+.global sigsetjmp
+sigsetjmp:
+       mov 4(%esp),%eax
+       mov 8(%esp),%ecx
+       mov %ecx,24(%eax)
+       jecxz 1f
+       add $28,%eax
+       push %eax
+       push $0
+       push $2
+       call sigprocmask
+       add $12,%esp
+1:     jmp setjmp
diff --git a/src/signal/kill.c b/src/signal/kill.c
new file mode 100644 (file)
index 0000000..cc4b51e
--- /dev/null
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int kill(pid_t pid, int sig)
+{
+       return syscall2(__NR_kill, pid, sig);
+}
diff --git a/src/signal/killpg.c b/src/signal/killpg.c
new file mode 100644 (file)
index 0000000..315ed44
--- /dev/null
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <errno.h>
+
+int killpg(pid_t pgid, int sig)
+{
+       if (pgid < 0) {
+               errno = EINVAL;
+               return -1;
+       }
+       return kill(-pgid, sig);
+}
diff --git a/src/signal/raise.c b/src/signal/raise.c
new file mode 100644 (file)
index 0000000..52f8b42
--- /dev/null
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int raise(int sig)
+{
+       return __syscall_kill(__syscall_getpid(), sig);
+}
diff --git a/src/signal/setitimer.c b/src/signal/setitimer.c
new file mode 100644 (file)
index 0000000..cacab03
--- /dev/null
@@ -0,0 +1,15 @@
+#include <sys/time.h>
+#include "syscall.h"
+
+int setitimer(int which, const struct itimerval *new, struct itimerval *old)
+{
+       int ret;
+       long knew[4] = {
+               new->it_interval.tv_sec, new->it_interval.tv_usec,
+               new->it_value.tv_sec, new->it_value.tv_usec
+       }, kold[4];
+
+       if (!(ret = syscall3(__NR_setitimer, which, (long)&knew, old ? (long)&kold : 0)) && old)
+               *old = (struct itimerval){ { kold[0], kold[1] }, { kold[2], kold[3] } };
+       return ret;
+}
diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c
new file mode 100644 (file)
index 0000000..4acd173
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include "syscall.h"
+#include "pthread_impl.h"
+
+static void restorer()
+{
+       syscall0(__NR_rt_sigreturn);
+}
+
+int __libc_sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
+{
+       struct {
+               void *handler;
+               unsigned long flags;
+               void (*restorer)(void);
+               sigset_t mask;
+       } ksa, kold;
+       long pksa=0, pkold=0;
+       if (sa) {
+               ksa.handler = sa->sa_handler;
+               ksa.flags = sa->sa_flags;
+               ksa.restorer = restorer;
+               ksa.mask = sa->sa_mask;
+               pksa = (long)&ksa;
+       }
+       if (old) pkold = (long)&kold;
+       if (syscall4(__NR_rt_sigaction, sig, pksa, pkold, 8))
+               return -1;
+       if (old) {
+               old->sa_handler = kold.handler;
+               old->sa_flags = kold.flags;
+               old->sa_mask = kold.mask;
+       }
+       return 0;
+}
+
+int __sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
+{
+       if (sig == SIGCANCEL || sig == SIGSYSCALL) {
+               errno = EINVAL;
+               return -1;
+       }
+       return __libc_sigaction(sig, sa, old);
+}
+
+weak_alias(__sigaction, sigaction);
diff --git a/src/signal/sigaddset.c b/src/signal/sigaddset.c
new file mode 100644 (file)
index 0000000..23e655d
--- /dev/null
@@ -0,0 +1,13 @@
+#include <signal.h>
+#include <errno.h>
+
+int sigaddset(sigset_t *set, int sig)
+{
+       unsigned s = sig-1;
+       if (s >= 8*sizeof(sigset_t)) {
+               errno = EINVAL;
+               return -1;
+       }
+       set->__bits[s/8/sizeof *set->__bits] |= 1UL<<(s&8*sizeof *set->__bits-1);
+       return 0;
+}
diff --git a/src/signal/sigaltstack.c b/src/signal/sigaltstack.c
new file mode 100644 (file)
index 0000000..3cc2d45
--- /dev/null
@@ -0,0 +1,8 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigaltstack(const stack_t *ss, stack_t *old)
+{
+       /* depends on kernel struct matching */
+       return syscall2(__NR_sigaltstack, (long)ss, (long)old);
+}
diff --git a/src/signal/sigdelset.c b/src/signal/sigdelset.c
new file mode 100644 (file)
index 0000000..14042fb
--- /dev/null
@@ -0,0 +1,13 @@
+#include <signal.h>
+#include <errno.h>
+
+int sigdelset(sigset_t *set, int sig)
+{
+       unsigned s = sig-1;
+       if (s >= 8*sizeof(sigset_t)) {
+               errno = EINVAL;
+               return -1;
+       }
+       set->__bits[s/8/sizeof *set->__bits] &=~(1UL<<(s&8*sizeof *set->__bits-1));
+       return 0;
+}
diff --git a/src/signal/sigemptyset.c b/src/signal/sigemptyset.c
new file mode 100644 (file)
index 0000000..91f77ad
--- /dev/null
@@ -0,0 +1,8 @@
+#include <signal.h>
+#include <string.h>
+
+int sigemptyset(sigset_t *set)
+{
+       memset(set, 0, sizeof *set);
+       return 0;
+}
diff --git a/src/signal/sigfillset.c b/src/signal/sigfillset.c
new file mode 100644 (file)
index 0000000..fab50a5
--- /dev/null
@@ -0,0 +1,8 @@
+#include <signal.h>
+#include <string.h>
+
+int sigfillset(sigset_t *set)
+{
+       memset(set, -1, sizeof *set);
+       return 0;
+}
diff --git a/src/signal/sighold.c b/src/signal/sighold.c
new file mode 100644 (file)
index 0000000..5b0f6b1
--- /dev/null
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sighold(int sig)
+{
+       sigset_t mask;
+
+       sigemptyset(&mask);
+       if (sigaddset(&mask, sig) < 0) return -1;
+       return sigprocmask(SIG_BLOCK, &mask, NULL);
+}
diff --git a/src/signal/sigignore.c b/src/signal/sigignore.c
new file mode 100644 (file)
index 0000000..98dff61
--- /dev/null
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sigignore(int sig)
+{
+       struct sigaction sa;
+
+       sigemptyset(&sa.sa_mask);
+       sa.sa_handler = SIG_IGN;
+       sa.sa_flags = 0;
+       return sigaction(sig, &sa, NULL);
+}
diff --git a/src/signal/siginterrupt.c b/src/signal/siginterrupt.c
new file mode 100644 (file)
index 0000000..60b3405
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include <signal.h>
+
+int siginterrupt(int sig, int flag)
+{
+       struct sigaction sa;
+
+       sigaction(sig, NULL, &sa);
+       if (flag) sa.sa_flags &= ~SA_RESTART;
+       else sa.sa_flags |= SA_RESTART;
+
+       return sigaction(sig, &sa, NULL);
+}
diff --git a/src/signal/sigismember.c b/src/signal/sigismember.c
new file mode 100644 (file)
index 0000000..afd29e5
--- /dev/null
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include <errno.h>
+
+int sigismember(const sigset_t *set, int sig)
+{
+       unsigned s = sig-1;
+       if (s >= 8*sizeof(sigset_t)) {
+               errno = EINVAL;
+               return -1;
+       }
+       return !!(set->__bits[s/8/sizeof *set->__bits] & 1UL<<(s&8*sizeof *set->__bits-1));
+}
diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c
new file mode 100644 (file)
index 0000000..33ac30e
--- /dev/null
@@ -0,0 +1,12 @@
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+
+void siglongjmp(sigjmp_buf buf, int ret)
+{
+       long *flag = buf + sizeof(jmp_buf)/sizeof(long);
+       sigset_t *mask = (void *)(flag + 1);
+       if (*flag)
+               sigprocmask (SIG_SETMASK, mask, NULL);
+       longjmp((void *)buf, ret);
+}
diff --git a/src/signal/signal.c b/src/signal/signal.c
new file mode 100644 (file)
index 0000000..0890276
--- /dev/null
@@ -0,0 +1,13 @@
+#include <signal.h>
+#include <stddef.h>
+#include "syscall.h"
+
+int __sigaction(int, const struct sigaction *, struct sigaction *);
+
+void (*signal(int sig, void (*func)(int)))(int)
+{
+       struct sigaction sa = { .sa_handler = func, .sa_flags = SA_RESTART };
+       if (__sigaction(sig, &sa, &sa) < 0)
+               return SIG_ERR;
+       return sa.sa_handler;
+}
diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c
new file mode 100644 (file)
index 0000000..263c00f
--- /dev/null
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sigpause(int sig)
+{
+       sigset_t mask;
+
+       if (sigprocmask(0, NULL, &mask) < 0 || sigdelset(&mask, sig) < 0)
+               return -1;
+       return sigsuspend(&mask);
+}
diff --git a/src/signal/sigpending.c b/src/signal/sigpending.c
new file mode 100644 (file)
index 0000000..7deda25
--- /dev/null
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigpending(sigset_t *set)
+{
+       return syscall2(__NR_rt_sigpending, (long)set, SYSCALL_SIGSET_SIZE);
+}
diff --git a/src/signal/sigprocmask.c b/src/signal/sigprocmask.c
new file mode 100644 (file)
index 0000000..e89f876
--- /dev/null
@@ -0,0 +1,23 @@
+#include <signal.h>
+#include "syscall.h"
+#include "libc.h"
+
+int __libc_sigprocmask(int how, const sigset_t *set, sigset_t *old)
+{
+       return syscall4(__NR_rt_sigprocmask, how, (long)set, (long)old, 8);
+}
+
+int __sigprocmask(int how, const sigset_t *set, sigset_t *old)
+{
+       sigset_t tmp;
+       /* Quickly mask out bits 32 and 33 (thread control signals) */
+       if (0 && how != SIG_UNBLOCK && (set->__bits[4/sizeof *set->__bits] & 3UL<<(32&8*sizeof *set->__bits-1))) {
+               tmp = *set;
+               set = &tmp;
+               tmp.__bits[4/sizeof *set->__bits] &= ~(3UL<<(32&8*sizeof *set->__bits-1));
+       }
+       return __libc_sigprocmask(how, set, old);
+}
+
+weak_alias(__sigprocmask, sigprocmask);
+weak_alias(__sigprocmask, pthread_sigmask);
diff --git a/src/signal/sigqueue.c b/src/signal/sigqueue.c
new file mode 100644 (file)
index 0000000..ce3abf6
--- /dev/null
@@ -0,0 +1,14 @@
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include "syscall.h"
+
+int sigqueue(pid_t pid, int sig, const union sigval value)
+{
+       siginfo_t si = {
+               .si_signo = sig,
+               .si_code = -1,
+               .si_value = value,
+       };
+       return syscall3(__NR_rt_sigqueueinfo, pid, sig, (long)&si);
+}
diff --git a/src/signal/sigrelse.c b/src/signal/sigrelse.c
new file mode 100644 (file)
index 0000000..b0b3024
--- /dev/null
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sigrelse(int sig)
+{
+       sigset_t mask;
+
+       sigemptyset(&mask);
+       if (sigaddset(&mask, sig) < 0) return -1;
+       return sigprocmask(SIG_UNBLOCK, &mask, NULL);
+}
diff --git a/src/signal/sigrtmax.c b/src/signal/sigrtmax.c
new file mode 100644 (file)
index 0000000..0ef2987
--- /dev/null
@@ -0,0 +1,4 @@
+int __libc_current_sigrtmax()
+{
+       return 64;
+}
diff --git a/src/signal/sigrtmin.c b/src/signal/sigrtmin.c
new file mode 100644 (file)
index 0000000..7ad06d2
--- /dev/null
@@ -0,0 +1,4 @@
+int __libc_current_sigrtmin()
+{
+       return 34;
+}
diff --git a/src/signal/sigset.c b/src/signal/sigset.c
new file mode 100644 (file)
index 0000000..1b6b38f
--- /dev/null
@@ -0,0 +1,28 @@
+#include <signal.h>
+#include <stdlib.h>
+
+void (*sigset(int sig, void (*handler)(int)))(int)
+{
+       struct sigaction sa, sa_old;
+       sigset_t mask;
+
+       sigemptyset(&mask);
+       if (sigaddset(&mask, sig) < 0)
+               return SIG_ERR;
+       
+       if (handler == SIG_HOLD) {
+               if (sigaction(sig, NULL, &sa_old) < 0)
+                       return SIG_ERR;
+               if (sigprocmask(SIG_BLOCK, &mask, &mask) < 0)
+                       return SIG_ERR;
+       } else {
+               sa.sa_handler = handler;
+               sa.sa_flags = 0;
+               sigemptyset(&sa.sa_mask);
+               if (sigaction(sig, &sa, &sa_old) < 0)
+                       return SIG_ERR;
+               if (sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
+                       return SIG_ERR;
+       }
+       return sigismember(&mask, sig) ? SIG_HOLD : sa_old.sa_handler;
+}
diff --git a/src/signal/sigsetjmp.c b/src/signal/sigsetjmp.c
new file mode 100644 (file)
index 0000000..a6667a2
--- /dev/null
@@ -0,0 +1,17 @@
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+
+/* !!! This function will not work unless the compiler performs
+ * tail call optimization. Machine-specific asm versions should
+ * be created instead even though the workaround (tail call)
+ * is entirely non-machine-specific... */
+
+int sigsetjmp(sigjmp_buf buf, int save)
+{
+       long *flag = buf + sizeof(jmp_buf)/sizeof(long);
+       sigset_t *mask = (void *)(flag + 1);
+       if ((*flag = save))
+               sigprocmask (SIG_SETMASK, NULL, mask);
+       return setjmp((void *)buf);
+}
diff --git a/src/signal/sigsuspend.c b/src/signal/sigsuspend.c
new file mode 100644 (file)
index 0000000..1acdab0
--- /dev/null
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigsuspend(const sigset_t *mask)
+{
+       return syscall2(__NR_rt_sigsuspend, (long)mask, sizeof(sigset_t));
+}
diff --git a/src/signal/sigtimedwait.c b/src/signal/sigtimedwait.c
new file mode 100644 (file)
index 0000000..155185d
--- /dev/null
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *timeout)
+{
+       long k_timeout[2];
+       if (timeout) {
+               k_timeout[0] = timeout->tv_sec;
+               k_timeout[1] = timeout->tv_nsec;
+       }
+       return syscall4(__NR_rt_sigtimedwait, (long)mask, (long)si, timeout ? (long)k_timeout : 0, SYSCALL_SIGSET_SIZE);
+}
diff --git a/src/signal/sigwait.c b/src/signal/sigwait.c
new file mode 100644 (file)
index 0000000..9569d6b
--- /dev/null
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stddef.h>
+
+int sigwait(const sigset_t *mask, int *sig)
+{
+       siginfo_t si;
+       if (sigtimedwait(mask, &si, NULL) < 0)
+               return -1;
+       *sig = si.si_signo;
+       return 0;
+}
diff --git a/src/signal/sigwaitinfo.c b/src/signal/sigwaitinfo.c
new file mode 100644 (file)
index 0000000..e79feb9
--- /dev/null
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include <stddef.h>
+
+int sigwaitinfo(const sigset_t *mask, siginfo_t *si)
+{
+       return sigtimedwait(mask, si, NULL);
+}
diff --git a/src/stat/chmod.c b/src/stat/chmod.c
new file mode 100644 (file)
index 0000000..cb310fe
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int chmod(const char *path, mode_t mode)
+{
+       return syscall2(__NR_chmod, (long)path, mode);
+}
diff --git a/src/stat/fchmod.c b/src/stat/fchmod.c
new file mode 100644 (file)
index 0000000..9189738
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int fchmod(int fd, mode_t mode)
+{
+       return syscall2(__NR_fchmod, fd, mode);
+}
diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c
new file mode 100644 (file)
index 0000000..f4f22b2
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int fchmodat(int fd, const char *path, mode_t mode, int flag)
+{
+       return syscall4(__NR_fchmodat, fd, (long)path, mode, flag);
+}
diff --git a/src/stat/fstat.c b/src/stat/fstat.c
new file mode 100644 (file)
index 0000000..5f64330
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/stat.h>
+#include "syscall.h"
+#include "libc.h"
+
+int fstat(int fd, struct stat *buf)
+{
+       return syscall2(__NR_fstat64, fd, (long)buf);
+}
+
+LFS64(fstat);
diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
new file mode 100644 (file)
index 0000000..22bc293
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/stat.h>
+#include "syscall.h"
+#include "libc.h"
+
+int fstatat(int fd, const char *path, struct stat *buf, int flag)
+{
+       return syscall4(__NR_fstatat64, fd, (long)path, (long)buf, flag);
+}
+
+LFS64(fstatat);
diff --git a/src/stat/fstatvfs.c b/src/stat/fstatvfs.c
new file mode 100644 (file)
index 0000000..83bd748
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/statvfs.h>
+#include "syscall.h"
+#include "libc.h"
+
+int fstatvfs(int fd, struct statvfs *buf)
+{
+       return syscall2(__NR_fstatfs64, fd, (long)buf);
+}
+
+weak_alias(fstatvfs, fstatfs);
+
+LFS64(fstatvfs);
+LFS64(fstatfs);
diff --git a/src/stat/lstat.c b/src/stat/lstat.c
new file mode 100644 (file)
index 0000000..afdb553
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/stat.h>
+#include "syscall.h"
+#include "libc.h"
+
+int lstat(const char *path, struct stat *buf)
+{
+       return syscall2(__NR_lstat64, (long)path, (long)buf);
+}
+
+LFS64(lstat);
diff --git a/src/stat/mkdir.c b/src/stat/mkdir.c
new file mode 100644 (file)
index 0000000..8295cad
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int mkdir(const char *path, mode_t mode)
+{
+       return syscall2(__NR_mkdir, (long)path, mode);
+}
diff --git a/src/stat/mkdirat.c b/src/stat/mkdirat.c
new file mode 100644 (file)
index 0000000..1fb3825
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int mkdirat(int fd, const char *path, mode_t mode)
+{
+       return syscall3(__NR_mkdirat, fd, (long)path, mode);
+}
diff --git a/src/stat/mkfifo.c b/src/stat/mkfifo.c
new file mode 100644 (file)
index 0000000..60efcf7
--- /dev/null
@@ -0,0 +1,6 @@
+#include <sys/stat.h>
+
+int mkfifo(const char *path, mode_t mode)
+{
+       return mknod(path, mode | S_IFIFO, 0);
+}
diff --git a/src/stat/mkfifoat.c b/src/stat/mkfifoat.c
new file mode 100644 (file)
index 0000000..d3a1f97
--- /dev/null
@@ -0,0 +1,6 @@
+#include <sys/stat.h>
+
+int mkfifoat(int fd, const char *path, mode_t mode)
+{
+       return mknodat(fd, path, mode | S_IFIFO, 0);
+}
diff --git a/src/stat/mknod.c b/src/stat/mknod.c
new file mode 100644 (file)
index 0000000..0123eee
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int mknod(const char *path, mode_t mode, dev_t dev)
+{
+       /* since dev_t is system-specific anyway we defer to the idiotic
+        * legacy-compatible bitfield mapping of the type.. at least we've
+        * made it large enough to leave space for future expansion.. */
+       return syscall3(__NR_mknod, (long)path, mode, dev & 0xffff);
+}
diff --git a/src/stat/mknodat.c b/src/stat/mknodat.c
new file mode 100644 (file)
index 0000000..b5687e4
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+int mknodat(int fd, const char *path, mode_t mode, dev_t dev)
+{
+       return syscall4(__NR_mknodat, fd, (long)path, mode, dev & 0xffff);
+}
diff --git a/src/stat/stat.c b/src/stat/stat.c
new file mode 100644 (file)
index 0000000..67640cc
--- /dev/null
@@ -0,0 +1,10 @@
+#include <sys/stat.h>
+#include "syscall.h"
+#include "libc.h"
+
+int stat(const char *path, struct stat *buf)
+{
+       return syscall2(__NR_stat64, (long)path, (long)buf);
+}
+
+LFS64(stat);
diff --git a/src/stat/statvfs.c b/src/stat/statvfs.c
new file mode 100644 (file)
index 0000000..55a05d5
--- /dev/null
@@ -0,0 +1,13 @@
+#include <sys/statvfs.h>
+#include "syscall.h"
+#include "libc.h"
+
+int statvfs(const char *path, struct statvfs *buf)
+{
+       return syscall2(__NR_statfs64, (long)path, (long)buf);
+}
+
+weak_alias(statvfs, statfs);
+
+LFS64(statvfs);
+LFS64(statfs);
diff --git a/src/stat/umask.c b/src/stat/umask.c
new file mode 100644 (file)
index 0000000..49cb48a
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/stat.h>
+#include "syscall.h"
+
+mode_t umask(mode_t mode)
+{
+       return syscall1(__NR_umask, mode);
+}
diff --git a/src/stdio/__fclose_ca.c b/src/stdio/__fclose_ca.c
new file mode 100644 (file)
index 0000000..e0b12a1
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+int __fclose_ca(FILE *f)
+{
+       return f->close(f);
+}
diff --git a/src/stdio/__fdopen.c b/src/stdio/__fdopen.c
new file mode 100644 (file)
index 0000000..6ad7c57
--- /dev/null
@@ -0,0 +1,52 @@
+#include "stdio_impl.h"
+
+FILE *__fdopen(int fd, const char *mode)
+{
+       FILE *f;
+       struct termios tio;
+       int plus = !!strchr(mode, '+');
+
+       /* Check for valid initial mode character */
+       if (!strchr("rwa", *mode)) return 0;
+
+       /* Allocate FILE+buffer or fail */
+       if (!(f=malloc(sizeof *f + UNGET + BUFSIZ))) return 0;
+
+       /* Zero-fill only the struct, not the buffer */
+       memset(f, 0, sizeof *f);
+
+       /* Impose mode restrictions */
+       if (!plus) f->flags = (*mode == 'r') ? F_NOWR : F_NORD;
+
+       /* Set append mode on fd if opened for append */
+       if (*mode == 'a') {
+               int flags = __syscall_fcntl(fd, F_GETFL, 0);
+               __syscall_fcntl(fd, F_SETFL, flags | O_APPEND);
+       }
+
+       f->fd = fd;
+       f->buf = (unsigned char *)f + sizeof *f + UNGET;
+       f->buf_size = BUFSIZ;
+
+       /* Activate line buffered mode for terminals */
+       f->lbf = EOF;
+       if (!(f->flags & F_NOWR) && !__syscall_ioctl(fd, TCGETS, &tio))
+               f->lbf = '\n';
+
+       /* Initialize op ptrs. No problem if some are unneeded. */
+       f->read = __stdio_read;
+       f->write = __stdio_write;
+       f->seek = __stdio_seek;
+       f->close = __stdio_close;
+
+       /* Add new FILE to open file list */
+       OFLLOCK();
+       f->next = ofl_head;
+       if (ofl_head) ofl_head->prev = f;
+       ofl_head = f;
+       OFLUNLOCK();
+
+       return f;
+}
+
+weak_alias(__fdopen, fdopen);
diff --git a/src/stdio/__fopen_rb_ca.c b/src/stdio/__fopen_rb_ca.c
new file mode 100644 (file)
index 0000000..57d9b73
--- /dev/null
@@ -0,0 +1,18 @@
+#include "stdio_impl.h"
+
+FILE *__fopen_rb_ca(const char *filename, FILE *f, unsigned char *buf, size_t len)
+{
+       memset(f, 0, sizeof *f);
+
+       f->fd = __syscall_open(filename, O_RDONLY, 0);
+       if (f->fd < 0) return 0;
+
+       f->flags = F_NOWR | F_PERM;
+       f->buf = buf + UNGET;
+       f->buf_size = len - UNGET;
+       f->read = __stdio_read;
+       f->seek = __stdio_seek;
+       f->close = __stdio_close;
+
+       return f;
+}
diff --git a/src/stdio/__fpending.c b/src/stdio/__fpending.c
new file mode 100644 (file)
index 0000000..a4334e2
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+size_t __fpending(FILE *f)
+{
+       return f->wend ? f->wpos - f->wbase : 0;
+}
diff --git a/src/stdio/__ofl.c b/src/stdio/__ofl.c
new file mode 100644 (file)
index 0000000..7d9652c
--- /dev/null
@@ -0,0 +1,3 @@
+#include "stdio_impl.h"
+
+struct ofl __ofl;
diff --git a/src/stdio/__overflow.c b/src/stdio/__overflow.c
new file mode 100644 (file)
index 0000000..e35104d
--- /dev/null
@@ -0,0 +1,52 @@
+#include "stdio_impl.h"
+
+static int overflow(FILE *f, int c)
+{
+       /* Initialize if we're not already writing */
+       if (!f->wend) {
+               /* Fail if we're in error state or unwritable. */
+               if (f->flags & (F_ERR|F_NOWR)) return EOF;
+
+               /* Set byte orientation -1,0=>-1; 1=>1 */
+               f->mode |= f->mode-1;
+
+               /* Clear read buffer (easier than summoning nasal demons) */
+               f->rpos = f->rend = f->rstop = 0;
+
+               /* Activate write through the buffer */
+               f->wpos = f->wbase = f->buf;
+               f->wend = f->buf + f->buf_size;
+               f->wstop = (f->lbf < 0) ? f->wend - 1 : 0;
+       }
+
+       /* Buffer can always hold at least 1 byte... */
+       if (c != EOF) {
+               *f->wpos++ = c;
+               if (f->wpos <= f->wstop && c != f->lbf) return c;
+       }
+       /* ...since if the next call fails, buffer is empty. */
+       if (f->write(f, f->wbase, f->wpos - f->wbase) < 0) {
+               f->flags |= F_ERR;
+               f->wpos = f->wbase = f->wend = f->wstop = 0;
+               return EOF;
+       }
+
+       /* Buffer is empty so reset position to beginning */
+       f->wpos = f->wbase;
+
+       return c;
+}
+
+int __overflow(FILE *f, int c)
+{
+       return overflow(f, c & 0xff);
+}
+
+int __oflow(FILE *f)
+{
+       overflow(f, EOF);
+       return (f->flags & F_ERR) ? EOF : 0;
+}
+
+/* Link flush-on-exit code iff any stdio write functions are linked. */
+int (*const __fflush_on_exit)(FILE *) = fflush;
diff --git a/src/stdio/__scanf.c b/src/stdio/__scanf.c
new file mode 100644 (file)
index 0000000..185615d
--- /dev/null
@@ -0,0 +1,487 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <float.h>
+
+#include "__scanf.h"
+
+static int read(rctx_t *r)
+{
+       if (--r->w < 0) return r->w = -1;
+       if (r->u) r->u = 0;
+       else r->read(r);
+       return r->c;
+}
+
+static void unread(rctx_t *r)
+{
+       //if (r->u || r->w < 0) return;
+       if (r->w < 0) return;
+       r->w++;
+       r->u = 1;
+}
+
+#define SIZE_hh -2
+#define SIZE_h  -1
+#define SIZE_def 0
+#define SIZE_l   1
+#define SIZE_ll  2
+#define SIZE_L   3
+
+static void store_int(void *dest, int size, int neg, unsigned long long i)
+{
+       if (!dest) return;
+       if (neg) i = -i;
+       switch (size) {
+       case SIZE_hh:
+               *(char *)dest = i;
+               break;
+       case SIZE_h:
+               *(short *)dest = i;
+               break;
+       case SIZE_def:
+               *(int *)dest = i;
+               break;
+       case SIZE_l:
+               *(long *)dest = i;
+               break;
+       case SIZE_ll:
+               *(long long *)dest = i;
+               break;
+       }
+}
+
+static void *arg_n(va_list ap, unsigned int n)
+{
+       void *p;
+       unsigned int i;
+       va_list ap2;
+       va_copy(ap2, ap);
+       for (i=n; i>1; i--) va_arg(ap2, void *);
+       p = va_arg(ap2, void *);
+       va_end(ap2);
+       return p;
+}
+
+int __scanf(rctx_t *r, const wchar_t *fmt, va_list ap)
+{
+       int mode=0;
+       int width;
+       int size;
+       const wchar_t *p, *z;
+       int c, l, t, m;
+       long long dummy;
+       char *s;
+       wchar_t *wcs;
+       mbstate_t st;
+       int wide = r->wide;
+       void *dest=NULL;
+       int invert;
+       unsigned long long i=0;
+       int neg=0;
+       int matches=0;
+       long double f;
+       int (*is_space)(int) = r->is_space;
+
+       for (p=fmt; *p; ) {
+               if (is_space(*p)) {
+                       do p++; while (is_space(*p));
+                       do r->w=1; while (is_space(read(r)));
+                       unread(r);
+                       continue;
+               } else if (*p != '%' || p[1] == '%') {
+                       if (*p == '%') p++;
+                       r->w = 1;
+                       if (*p++ != read(r))
+                               goto match_fail;
+                       continue;
+               }
+               p++;
+               if (mode != 1) {
+                       for (z=p; isdigit(*z); z++);
+                       if (*z != '$' && *z != '*') {
+                               if (mode == 0) mode = 1;
+                               else goto fmt_fail;
+                       } else if (*z != '*') {
+                               int pos = 0;
+                               mode = 2;
+                               for (; p<z; p++) {
+                                       pos = 10*pos + *p - '0';
+                               }
+                               p++;
+                               if (!pos) goto fmt_fail;
+                               dest = arg_n(ap, pos);
+                       }
+               }
+               if (*p == '*') {
+                       dest = NULL;
+                       p++;
+               } else if (mode == 1) {
+                       dest = va_arg(ap, void *);
+               }
+               
+               if (!*p) goto fmt_fail;
+
+               width = 0;
+               for (; isdigit(*p); p++) {
+                       width = 10*width + *p - '0';
+               }
+
+               size = 0;
+               switch (*p++) {
+               case 0:
+                       goto fmt_fail;
+               case 'h':
+                       if (*p == 'h') p++, size = SIZE_hh;
+                       else size = SIZE_h;
+                       break;
+               case 'l':
+                       if (*p == 'l') p++, size = SIZE_ll;
+                       else size = SIZE_l;
+                       break;
+               case 'j':
+                       size = SIZE_ll;
+                       break;
+               case 'z':
+               case 't':
+                       size = SIZE_l;
+                       break;
+               case 'L':
+                       size = SIZE_L;
+                       break;
+               case 'd': case 'i': case 'o': case 'u': case 'x':
+               case 'a': case 'e': case 'f': case 'g':
+               case 'A': case 'E': case 'F': case 'G': case 'X':
+               case 's': case 'c': case '[':
+               case 'S': case 'C':
+               case 'p': case 'n':
+                       p--;
+                       break;
+               default:
+                       goto fmt_fail;
+               }
+
+               t = *p++;
+
+               switch (t) {
+               case 'C':
+               case 'c':
+                       if (width < 1) width = 1;
+               case 's':
+                       if (size == SIZE_l) t &= ~0x20;
+               case 'd': case 'i': case 'o': case 'u': case 'x':
+               case 'a': case 'e': case 'f': case 'g':
+               case 'A': case 'E': case 'F': case 'G': case 'X':
+               case '[': case 'S':
+               case 'p': case 'n':
+                       if (width < 1) width = INT_MAX;
+                       break;
+               default:
+                       goto fmt_fail;
+               }
+
+               r->w = width;
+
+               if (t != 'n') {
+                       if (read(r) < 0) goto input_fail;
+                       unread(r);
+               }
+
+               switch (t) {
+               case 'n':
+                       store_int(dest, size, 0, r->l - r->u);
+                       /* do not increment match count, etc! */
+                       continue;
+               case 'C':
+                       wcs = dest ? dest : (void *)&dummy;
+                       st = (mbstate_t){ 0 };
+                       while ((c=read(r)) >= 0) {
+                               if (wide) {
+                                       if (dest) *wcs++ = c;
+                               } else {
+                                       char ch = c;
+                                       switch (mbrtowc(wcs, &ch, 1, &st)) {
+                                       case -1:
+                                               goto enc_fail;
+                                       case -2:
+                                               break;
+                                       default:
+                                               if (dest) wcs++;
+                                       }
+                               }
+                       }
+                       if (r->w > 0) goto match_fail;
+                       break;
+               case 'c':
+                       s = dest ? dest : (void *)&dummy;
+                       while ((c=read(r)) >= 0) {
+                               if (wide) {
+                                       if ((l=wctomb(s, c)) < 0)
+                                               goto enc_fail;
+                                       if (dest) s += l;
+                               } else {
+                                       if (dest) *s++ = c;
+                               }
+                       }
+                       if (r->w > 0) goto match_fail;
+                       break;
+               case '[':
+                       wcs = dest ? dest : (void *)&dummy;
+                       s = dest ? dest : (void *)&dummy;
+                       if (!wide && size == SIZE_l) st = (mbstate_t){ 0 };
+
+                       if (*p == '^') p++, invert = 1;
+                       else invert = 0;
+
+                       if (wide) {
+                               for (m=0; (c=read(r)) >= 0; m=1) {
+                                       for (z=p; *z && *z != c && (*z != ']' || z==p); z++);
+                                       if (!*z) goto fmt_fail;
+                                       if (*z == c && (*z != ']' || z==p)) {
+                                               if (invert) break;
+                                       } else {
+                                               if (!invert) break;
+                                       }
+                                       if (size == SIZE_l) {
+                                               if (dest) *wcs++ = c;
+                                       } else {
+                                               if ((l=wctomb(s, c)) < 0)
+                                                       goto enc_fail;
+                                               if (dest) s += l;
+                                       }
+                               }
+                               for (p++; *p && *p != ']'; p++);
+                               p++;
+                       } else {
+                               unsigned char scanset[257];
+                               memset(scanset, invert, sizeof scanset);
+                               scanset[0] = 0;
+                               for (z=p; *z && (*z != ']' || z==p); z++)
+                                       scanset[1+*z] = 1-invert;
+                               if (!*z) goto fmt_fail;
+                               p=z+1;
+                               c=0;
+                               for (m=0; scanset[(c=read(r))+1]; m=1) {
+                                       if (size == SIZE_l) {
+                                               char ch = c;
+                                               switch (mbrtowc(wcs, &ch, 1, &st)) {
+                                               case -1:
+                                                       goto enc_fail;
+                                               case -2:
+                                                       break;
+                                               default:
+                                                       if (dest) wcs++;
+                                               }
+                                       } else {
+                                               if (dest) *s++ = c;
+                                       }
+                               }
+                       }
+                       if (!m) goto match_fail;
+                       if (dest) {
+                               if (size == SIZE_l) *wcs++ = 0;
+                               else *s++ = 0;
+                       }
+                       break;
+               default:
+                       /* read unlimited number of spaces, then reset width */
+                       do r->w = 1; while (is_space(c = read(r)));
+                       if (c < 0) goto input_fail;
+                       unread(r);
+                       r->w = width;
+               }
+
+               switch (t) {
+               case 'p':
+               case 'X':
+                       t = 'x';
+               case 'd':
+               case 'i':
+               case 'o':
+               case 'u':
+               case 'x':
+                       i = m = neg = 0;
+                       if ((c=read(r)) == '-') neg=1;
+                       else if (c != '+') unread(r);
+                       switch (t) {
+                       case 'i':
+                       case 'x':
+                               if ((c=read(r)) != '0') {
+                                       if (t == 'i') t = 'd';
+                                       unread(r);
+                                       break;
+                               }
+                               if (((c=read(r))|0x20) != 'x') {
+                                       if (t == 'i') {
+                                               t = 'o';
+                                               /* lone 0 is valid octal */
+                                               if ((unsigned)(c-'0') >= 8) {
+                                                       m = 1;
+                                                       goto int_finish;
+                                               }
+                                       }
+                                       unread(r);
+                                       break;
+                               }
+                               t = 'x';
+                       }
+               }
+               
+               switch (t) {
+               case 'd':
+               case 'u':
+                       for (m=0; isdigit(c=read(r)); m=1)
+                               i = 10*i + c-'0';
+                       goto int_finish;
+               case 'o':
+                       for (m=0; (unsigned)(c=read(r))-'0' < 8; m=1)
+                               i = (i<<3) + c-'0';
+                       goto int_finish;
+               case 'x':
+                       for (m=0; ; m=1) {
+                               if (isdigit(c=read(r))) {
+                                       i = (i<<4) + c-'0';
+                               } else if ((unsigned)(c|0x20)-'a' < 6) {
+                                       i = (i<<4) + (c|0x20)-'a'+10;
+                               } else break;
+                       }
+               int_finish:
+                       if (!m) goto match_fail;
+                       store_int(dest, size, neg, i);
+                       break;
+               case 'a':
+               case 'e':
+               case 'f':
+               case 'g':
+                       f = 0.0;
+                       neg = m = 0;
+                       if ((c=read(r)) == '-') neg=1;
+                       else if (c != '+') unread(r);
+                       /* FIXME: check for INF/NAN strings here */
+                       if (read(r)=='0' && (m=1, (read(r)|0x20) == 'x'))
+                               goto hexfloat;
+                       else unread(r);
+                       for (; isdigit(c=read(r)); m=1)
+                               f = 10.0 * f + (c-'0');
+                       if (c=='.') {
+                               double mag = 10.0;
+                               for (; isdigit(c=read(r)); mag*=10.0)
+                                       f += (c-'0')/mag;
+                       }
+                       if ((c|0x20)=='e') {
+                               int ex=0, en=0;
+                               m = 0;
+                               if ((c=read(r))=='-') en=1;
+                               else if (c!='+') unread(r);
+                               for (; isdigit(c=read(r)); m=1)
+                                       if (ex < LDBL_MAX_10_EXP)
+                                               ex = 10 * ex + (c-'0');
+                               if (ex > LDBL_MAX_10_EXP)
+                                       f = en ? 0 : INFINITY;
+                               else {
+                                       if (en) while (ex--) f/=10.0;
+                                       else while (ex--) f*=10.0;
+                               }
+                       }
+                       goto writefloat;
+hexfloat:
+                       m = 0;
+                       for (; isxdigit(c=read(r)); m=1)
+                               if (isdigit(c)) f = 16.0*f + (c-'0');
+                               else f = 16.0*f + ((c|32)-'a'+10);
+                       if (c=='.') {
+                               double mag = 1/16.0;
+                               for (; isxdigit(c=read(r)); mag*=1/16.0)
+                                       if (isdigit(c)) f += (c-'0')*mag;
+                                       else f += ((c|32)-'a'+10)*mag;
+                       }
+                       if ((c|0x20)=='p') {
+                               int ex=0, en=0;
+                               m = 0;
+                               if ((c=read(r))=='-') en=1;
+                               else if (c!='+') unread(r);
+                               for (; isdigit(c=read(r)); m=1)
+                                       if (ex < LDBL_MAX_EXP)
+                                               ex = 10 * ex + (c-'0');
+                               if (ex > LDBL_MAX_EXP)
+                                       f = en ? 0 : INFINITY;
+                               else {
+                                       if (en) while (ex--) f*=0.5;
+                                       else while (ex--) f*=2.0;
+                               }
+                       }
+writefloat:
+                       if (!m) goto match_fail;
+                       if (neg) f *= -1.0;
+                       if (dest) switch (size) {
+                       case SIZE_def:
+                               *(float *)dest = f;
+                               break;
+                       case SIZE_l:
+                               *(double *)dest = f;
+                               break;
+                       case SIZE_L:
+                               *(long double *)dest = f;
+                               break;
+                       }
+                       break;
+               case 'S':
+                       wcs = dest ? dest : (void *)&dummy;
+                       st = (mbstate_t){ 0 };
+                       while((c=read(r)) >= 0) {
+                               if (wide) {
+                                       if (is_space(c)) break;
+                                       if (dest) *wcs++ = c;
+                               } else {
+                                       char ch = c;
+                                       if (is_space(c)) break;
+                                       switch (mbrtowc(wcs, &ch, 1, &st)) {
+                                       case -1:
+                                               goto enc_fail;
+                                       case -2:
+                                               break;
+                                       default:
+                                               if (dest) wcs++;
+                                       }
+                               }
+                       }
+                       if (dest) *wcs++ = 0;
+                       break;
+               case 's':
+                       s = dest ? dest : (void *)&dummy;
+                       while((c=read(r)) >= 0) {
+                               if (wide) {
+                                       if (is_space(c)) break;
+                                       if ((l=wctomb(s, c)) < 0)
+                                               goto enc_fail;
+                                       if (dest) s += l;
+                               } else {
+                                       if (is_space(c)) break;
+                                       if (dest) *s++ = c;
+                               }
+                       }
+                       if (dest) *s++ = 0;
+                       break;
+               }
+
+               /* unread will do nothing if field width was exhausted */
+               unread(r);
+               if (dest) matches++;
+       }
+       return matches;
+enc_fail:
+       errno = EILSEQ;
+fmt_fail:
+input_fail:
+       if (!matches) matches--;
+match_fail:
+       unread(r);
+       return matches;
+}
diff --git a/src/stdio/__scanf.h b/src/stdio/__scanf.h
new file mode 100644 (file)
index 0000000..e549b97
--- /dev/null
@@ -0,0 +1,16 @@
+#include <wchar.h>
+
+typedef struct rctx
+{
+       void (*read)(struct rctx *);
+       void *opaque;
+       int wide;
+       int (*is_space)();
+       int l;
+       int e;
+       int c;
+       int u;
+       int w;
+} rctx_t;
+
+int __scanf(rctx_t *, const wchar_t *, va_list);
diff --git a/src/stdio/__stdio_close.c b/src/stdio/__stdio_close.c
new file mode 100644 (file)
index 0000000..24fef33
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+int __stdio_close(FILE *f)
+{
+       return __syscall_close(f->fd);
+}
diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c
new file mode 100644 (file)
index 0000000..ee7e125
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
+{
+       return __syscall_read(f->fd, buf, len);
+}
diff --git a/src/stdio/__stdio_seek.c b/src/stdio/__stdio_seek.c
new file mode 100644 (file)
index 0000000..fdb9fe7
--- /dev/null
@@ -0,0 +1,15 @@
+#include "stdio_impl.h"
+
+static off_t retneg1(FILE *f, off_t off, int whence)
+{
+       return -1;
+}
+
+off_t __stdio_seek(FILE *f, off_t off, int whence)
+{
+       off_t ret = __syscall_lseek(f->fd, off, whence);
+       /* Detect unseekable files and optimize future failures out */
+       if (ret < 0 && off == 0 && whence == SEEK_CUR)
+               f->seek = retneg1;
+       return ret;
+}
diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c
new file mode 100644 (file)
index 0000000..7854562
--- /dev/null
@@ -0,0 +1,9 @@
+#include "stdio_impl.h"
+
+size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
+{
+       const unsigned char *stop = buf+len;
+       ssize_t cnt = 1;
+       for (; buf<stop && (cnt=__syscall_write(f->fd, buf, len))>0; buf+=cnt);
+       return len-(stop-buf);
+}
diff --git a/src/stdio/__uflow.c b/src/stdio/__uflow.c
new file mode 100644 (file)
index 0000000..5a51d61
--- /dev/null
@@ -0,0 +1,7 @@
+#include "stdio_impl.h"
+
+int __uflow(FILE *f)
+{
+       if (__underflow(f) < 0) return EOF;
+       else return *f->rpos++;
+}
diff --git a/src/stdio/__underflow.c b/src/stdio/__underflow.c
new file mode 100644 (file)
index 0000000..b769f4e
--- /dev/null
@@ -0,0 +1,38 @@
+#include "stdio_impl.h"
+
+int __underflow(FILE *f)
+{
+       ssize_t cnt;
+
+       /* Read from buffer (Do we ever get called when this is true??) */
+       if (f->rpos < f->rstop) return *f->rpos;
+
+       /* Initialize if we're not already reading */
+       if (!f->rstop) {
+               /* Fail immediately if unreadable, eof, or error state. */
+               if (f->flags & (F_EOF|F_ERR|F_NORD)) return EOF;
+
+               /* Set byte orientation -1,0=>-1; 1=>1 */
+               f->mode |= f->mode-1;
+
+               /* Flush any unwritten output; fail on error. */
+               if (f->wpos > f->buf && __oflow(f)) return EOF;
+
+               /* Disallow writes to buffer. */
+               f->wstop = 0;
+       }
+
+       /* Perform the underlying read operation */
+       if ((cnt=f->read(f, f->buf, f->buf_size)) + 1 <= 1) {
+               /* Set flags and leave read mode */
+               f->flags |= F_EOF | (cnt & F_ERR);
+               f->rpos = f->rend = f->rstop = 0;
+               return EOF;
+       }
+
+       /* Setup buffer pointers for reading from buffer */
+       f->rpos = f->buf;
+       f->rend = f->rstop = f->buf + cnt;
+
+       return *f->rpos;
+}
diff --git a/src/stdio/asprintf.c b/src/stdio/asprintf.c
new file mode 100644 (file)
index 0000000..79e59c2
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int vasprintf(char **, const char *, va_list);
+
+int asprintf(char **s, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vasprintf(s, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/clearerr.c b/src/stdio/clearerr.c
new file mode 100644 (file)
index 0000000..3bf94d3
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+void clearerr(FILE *f)
+{
+       FLOCK(f);
+       f->flags &= ~(F_EOF|F_ERR);
+       FUNLOCK(f);
+}
+
+weak_alias(clearerr, clearerr_unlocked);
diff --git a/src/stdio/dprintf.c b/src/stdio/dprintf.c
new file mode 100644 (file)
index 0000000..fa28322
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int dprintf(int fd, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vdprintf(fd, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c
new file mode 100644 (file)
index 0000000..26bc37e
--- /dev/null
@@ -0,0 +1,21 @@
+#include "stdio_impl.h"
+
+int fclose(FILE *f)
+{
+       int r;
+       int perm = f->flags & F_PERM;
+
+       if (!perm) {
+               OFLLOCK();
+               if (f->prev) f->prev->next = f->next;
+               if (f->next) f->next->prev = f->prev;
+               if (ofl_head == f) ofl_head = f->next;
+               OFLUNLOCK();
+       }
+
+       r = fflush(f) | f->close(f);
+
+       if (!perm) free(f);
+       
+       return r;
+}
diff --git a/src/stdio/feof.c b/src/stdio/feof.c
new file mode 100644 (file)
index 0000000..f2b739b
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+#undef feof
+
+int feof(FILE *f)
+{
+       return !!(f->flags & F_EOF);
+}
+
+weak_alias(feof, feof_unlocked);
diff --git a/src/stdio/ferror.c b/src/stdio/ferror.c
new file mode 100644 (file)
index 0000000..f535fbe
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+#undef ferror
+
+int ferror(FILE *f)
+{
+       return !!(f->flags & F_ERR);
+}
+
+weak_alias(ferror, ferror_unlocked);
diff --git a/src/stdio/fflush.c b/src/stdio/fflush.c
new file mode 100644 (file)
index 0000000..cf3f5b0
--- /dev/null
@@ -0,0 +1,50 @@
+#include "stdio_impl.h"
+
+static int __fflush_unlocked(FILE *f)
+{
+       /* If writing, flush output. */
+       if (f->wpos > f->buf && __oflow(f)) return -1;
+
+       /* If reading, sync position, per POSIX */
+       if (f->rpos < f->rend) f->seek(f, f->rpos-f->rend, SEEK_CUR);
+       f->rpos = f->rend;
+
+       /* Hook for special behavior on flush */
+       if (f->flush) f->flush(f);
+
+       return (f->flags & F_ERR) ? EOF : 0;
+}
+
+/* stdout.c will override this if linked */
+static FILE *const __dummy = 0;
+weak_alias(__dummy, __stdout_to_flush);
+
+int fflush(FILE *f)
+{
+       int r;
+       FILE *next;
+
+       if (f) {
+               FLOCK(f);
+               r = __fflush_unlocked(f);
+               FUNLOCK(f);
+               return r;
+       }
+
+       r = __stdout_to_flush ? fflush(__stdout_to_flush) : 0;
+
+       OFLLOCK();
+       for (f=ofl_head; f; f=next) {
+               FLOCK(f);
+               OFLUNLOCK();
+               r |= __fflush_unlocked(f);
+               OFLLOCK();
+               next = f->next;
+               FUNLOCK(f);
+       }
+       OFLUNLOCK();
+       
+       return r;
+}
+
+weak_alias(__fflush_unlocked, fflush_unlocked);
diff --git a/src/stdio/fgetc.c b/src/stdio/fgetc.c
new file mode 100644 (file)
index 0000000..3a7f1e3
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+int fgetc(FILE *f)
+{
+       int c;
+       FLOCK(f);
+       c = f->rpos < f->rstop ? *f->rpos++ : __uflow(f);
+       FUNLOCK(f);
+       return c;
+}
diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c
new file mode 100644 (file)
index 0000000..5b663d1
--- /dev/null
@@ -0,0 +1,11 @@
+#include "stdio_impl.h"
+
+int fgetpos(FILE *f, fpos_t *pos)
+{
+       off_t off = __ftello(f);
+       if (off < 0) return -1;
+       *(off_t *)pos = off;
+       return 0;
+}
+
+LFS64(fgetpos);
diff --git a/src/stdio/fgets.c b/src/stdio/fgets.c
new file mode 100644 (file)
index 0000000..7939303
--- /dev/null
@@ -0,0 +1,34 @@
+#include "stdio_impl.h"
+
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+
+char *fgets(char *s, int n, FILE *f)
+{
+       char *p = s;
+       unsigned char *z;
+       size_t k;
+
+       if (!n--) return 0;
+
+       FLOCK(f);
+
+       while (n && !feof(f)) {
+               z = memchr(f->rpos, '\n', f->rend - f->rpos);
+               k = z ? z - f->rpos + 1 : f->rend - f->rpos;
+               k = MIN(k, n);
+               memcpy(p, f->rpos, k);
+               f->rpos += k;
+               p += k;
+               n -= k;
+               if (z) break;
+               __underflow(f);
+       }
+       *p = 0;
+       if (ferror(f)) p = s;
+
+       FUNLOCK(f);
+
+       return (p == s) ? 0 : s;
+}
+
+weak_alias(fgets, fgets_unlocked);
diff --git a/src/stdio/fgetwc.c b/src/stdio/fgetwc.c
new file mode 100644 (file)
index 0000000..c990545
--- /dev/null
@@ -0,0 +1,51 @@
+#include "stdio_impl.h"
+
+wint_t __fgetwc_unlocked(FILE *f)
+{
+       mbstate_t st = { 0 };
+       wchar_t wc;
+       int c;
+       unsigned char b;
+       size_t l;
+
+       f->mode |= f->mode+1;
+
+       /* Convert character from buffer if possible */
+       if (f->rpos < f->rend) {
+               l = mbrtowc(&wc, f->rpos, f->rend - f->rpos, &st);
+               if (l+2 >= 2) {
+                       f->rpos += l + !l; /* l==0 means 1 byte, null */
+                       return wc;
+               }
+               if (l == -1) {
+                       f->rpos++;
+                       return WEOF;
+               }
+       } else l = -2;
+
+       /* Convert character byte-by-byte from __uflow */
+       while (l == -2) {
+               b = c = __uflow(f);
+               if (c < 0) {
+                       if (!mbsinit(&st)) errno = EILSEQ;
+                       return WEOF;
+               }
+               l = mbrtowc(&wc, &b, 1, &st);
+               if (l == -1) return WEOF;
+       }
+
+       FUNLOCK(f);
+       return wc;
+}
+
+wint_t fgetwc(FILE *f)
+{
+       wint_t c;
+       FLOCK(f);
+       c = __fgetwc_unlocked(f);
+       FUNLOCK(f);
+       return c;
+}
+
+weak_alias(__fgetwc_unlocked, fgetwc_unlocked);
+weak_alias(__fgetwc_unlocked, getwc_unlocked);
diff --git a/src/stdio/fgetws.c b/src/stdio/fgetws.c
new file mode 100644 (file)
index 0000000..2e76b56
--- /dev/null
@@ -0,0 +1,27 @@
+#include "stdio_impl.h"
+
+wint_t __fgetwc_unlocked(FILE *);
+
+wchar_t *fgetws(wchar_t *s, int n, FILE *f)
+{
+       wchar_t *p = s;
+
+       if (!n--) return s;
+
+       FLOCK(f);
+
+       for (; n; n--) {
+               wint_t c = __fgetwc_unlocked(f);
+               if (c == WEOF) break;
+               *p++ = c;
+               if (c == '\n') break;
+       }
+       *p = 0;
+       if (ferror(f)) p = s;
+
+       FUNLOCK(f);
+
+       return (p == s) ? NULL : s;
+}
+
+weak_alias(fgetws, fgetws_unlocked);
diff --git a/src/stdio/fileno.c b/src/stdio/fileno.c
new file mode 100644 (file)
index 0000000..9ffb26d
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+int fileno(FILE *f)
+{
+       return f->fd;
+}
+
+weak_alias(fileno, fileno_unlocked);
diff --git a/src/stdio/fmemopen.c b/src/stdio/fmemopen.c
new file mode 100644 (file)
index 0000000..77a6074
--- /dev/null
@@ -0,0 +1,16 @@
+#if 0
+#include "stdio_impl.h"
+
+static ssize_t mread(FILE *f, unsigned char *buf, size_t len)
+{
+       memcpy(buf, 
+}
+
+FILE *fmemopen(void *buf, size_t size, const char *mode)
+{
+       FILE *f = calloc(sizeof(FILE), 1);
+       if (!f) return 0;
+       
+       //
+}
+#endif
diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c
new file mode 100644 (file)
index 0000000..670cf5f
--- /dev/null
@@ -0,0 +1,34 @@
+#include "stdio_impl.h"
+
+FILE *fopen(const char *filename, const char *mode)
+{
+       FILE *f;
+       int fd;
+       int flags;
+       int plus = !!strchr(mode, '+');
+
+       /* Check for valid initial mode character */
+       if (!strchr("rwa", *mode)) {
+               errno = EINVAL;
+               return 0;
+       }
+
+       /* Compute the flags to pass to open() */
+       if (plus) flags = O_RDWR;
+       else if (*mode == 'r') flags = O_RDONLY;
+       else flags = O_WRONLY;
+       if (*mode != 'r') flags |= O_CREAT;
+       if (*mode == 'w') flags |= O_TRUNC;
+       if (*mode == 'a') flags |= O_APPEND;
+
+       fd = __syscall_open(filename, flags, 0666);
+       if (fd < 0) return 0;
+
+       f = __fdopen(fd, mode);
+       if (f) return f;
+
+       __syscall_close(fd);
+       return 0;
+}
+
+LFS64(fopen);
diff --git a/src/stdio/fprintf.c b/src/stdio/fprintf.c
new file mode 100644 (file)
index 0000000..a220cc1
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int fprintf(FILE *f, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vfprintf(f, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/fputc.c b/src/stdio/fputc.c
new file mode 100644 (file)
index 0000000..ec85938
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+int fputc(int c, FILE *f)
+{
+       FLOCK(f);
+       if (c != f->lbf && f->wpos + 1 < f->wend) *f->wpos++ = c;
+       else c = __overflow(f, c);
+       FUNLOCK(f);
+       return c;
+}
diff --git a/src/stdio/fputs.c b/src/stdio/fputs.c
new file mode 100644 (file)
index 0000000..e6bdb20
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+int fputs(const char *s, FILE *f)
+{
+       size_t l = strlen(s);
+       if (!l) return 0;
+       return (int)fwrite(s, l, 1, f) - 1;
+}
+
+weak_alias(fputs, fputs_unlocked);
diff --git a/src/stdio/fputwc.c b/src/stdio/fputwc.c
new file mode 100644 (file)
index 0000000..b48bb74
--- /dev/null
@@ -0,0 +1,33 @@
+#include "stdio_impl.h"
+
+wint_t __fputwc_unlocked(wchar_t c, FILE *f)
+{
+       char mbc[MB_LEN_MAX];
+       int l;
+
+       f->mode |= f->mode+1;
+
+       if (isascii(c)) {
+               if (c != f->lbf && f->wpos + 1 < f->wend) *f->wpos++ = c;
+               else c = __overflow(f, c);
+       } else if (f->wpos + MB_LEN_MAX < f->wend) {
+               l = wctomb(f->wpos, c);
+               if (l < 0) c = WEOF;
+               else f->wpos += l;
+       } else {
+               l = wctomb(mbc, c);
+               if (l < 0 || __fwritex(mbc, l, f) < l) c = WEOF;
+       }
+       return c;
+}
+
+wint_t fputwc(wchar_t c, FILE *f)
+{
+       FLOCK(f);
+       c = __fputwc_unlocked(c, f);
+       FUNLOCK(f);
+       return 0;
+}
+
+weak_alias(__fputwc_unlocked, fputwc_unlocked);
+weak_alias(__fputwc_unlocked, putwc_unlocked);
diff --git a/src/stdio/fputws.c b/src/stdio/fputws.c
new file mode 100644 (file)
index 0000000..9057853
--- /dev/null
@@ -0,0 +1,23 @@
+#include "stdio_impl.h"
+
+int fputws(const wchar_t *ws, FILE *f)
+{
+       unsigned char buf[BUFSIZ];
+       size_t l=0;
+
+       FLOCK(f);
+
+       f->mode |= f->mode+1;
+
+       while (ws && (l = wcsrtombs(buf, (void*)&ws, sizeof buf, 0))+1 > 1)
+               if (__fwritex(buf, l, f) < l) {
+                       FUNLOCK(f);
+                       return -1;
+               }
+
+       FUNLOCK(f);
+
+       return l; /* 0 or -1 */
+}
+
+weak_alias(fputws, fputws_unlocked);
diff --git a/src/stdio/fread.c b/src/stdio/fread.c
new file mode 100644 (file)
index 0000000..0fa0b2a
--- /dev/null
@@ -0,0 +1,49 @@
+#include "stdio_impl.h"
+
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+
+size_t fread(void *destv, size_t size, size_t nmemb, FILE *f)
+{
+       unsigned char *dest = destv;
+       size_t len = size*nmemb, l = len, k;
+
+       /* Never touch the file if length is zero.. */
+       if (!l) return 0;
+
+       FLOCK(f);
+
+       for (;;) {
+               /* First exhaust the buffer. */
+               k = MIN(f->rend - f->rpos, l);
+               memcpy(dest, f->rpos, k);
+               f->rpos += k;
+               dest += k;
+               l -= k;
+
+               /* Stop on EOF or errors */
+               if (f->flags & (F_EOF|F_ERR|F_NORD)) goto eof;
+
+               /* Done? Or going unbuffered? */
+               if (!l || l > f->buf_size/2) break;
+
+               /* Otherwise, refill & read thru buffer. */
+               __underflow(f);
+       }
+
+       /* Read the remainder directly */
+       for (; l; l-=k, dest+=k) {
+               k = f->read(f, dest, l);
+               if (k+1<=1) {
+                       f->flags |= F_EOF | (F_ERR & k);
+                       goto eof;
+               }
+       }
+
+       FUNLOCK(f);
+       return nmemb;
+eof:
+       FUNLOCK(f);
+       return (len-l)/size;
+}
+
+weak_alias(fread, fread_unlocked);
diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c
new file mode 100644 (file)
index 0000000..8d3af9f
--- /dev/null
@@ -0,0 +1,47 @@
+#include "stdio_impl.h"
+
+/* The basic idea of this implementation is to open a new FILE,
+ * hack the necessary parts of the new FILE into the old one, then
+ * close the new FILE. */
+
+/* Locking is not necessary because, in the event of failure, the stream
+ * passed to freopen is invalid as soon as freopen is called. */
+
+FILE *freopen(const char *filename, const char *mode, FILE *f)
+{
+       int fl;
+       FILE *f2;
+
+       fflush(f);
+
+       if (!filename) {
+               f2 = fopen("/dev/null", mode);
+               if (!f2) goto fail;
+               fl = __syscall_fcntl(f2->fd, F_GETFL, 0);
+               if (fl < 0 || __syscall_fcntl(f->fd, F_SETFL, fl) < 0)
+                       goto fail2;
+       } else {
+               f2 = fopen(filename, mode);
+               if (!f2) goto fail;
+               if (__syscall_dup2(f2->fd, f->fd) < 0)
+                       goto fail2;
+       }
+
+       f->flags = (f->flags & F_PERM) | f2->flags;
+       f->read = f2->read;
+       f->write = f2->write;
+       f->seek = f2->seek;
+       f->close = f2->close;
+       f->flush = f2->flush;
+
+       fclose(f2);
+       return f;
+
+fail2:
+       fclose(f2);
+fail:
+       fclose(f);
+       return NULL;
+}
+
+LFS64(freopen);
diff --git a/src/stdio/fscanf.c b/src/stdio/fscanf.c
new file mode 100644 (file)
index 0000000..51fc9b3
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int fscanf(FILE *f, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vfscanf(f, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c
new file mode 100644 (file)
index 0000000..bfaad37
--- /dev/null
@@ -0,0 +1,38 @@
+#include "stdio_impl.h"
+
+int __fseeko_unlocked(FILE *f, off_t off, int whence)
+{
+       /* Adjust relative offset for unread data in buffer, if any. */
+       if (whence == SEEK_CUR) off -= f->rend - f->rpos;
+
+       /* If writing, flush output. */
+       if (f->wpos > f->buf && __oflow(f)) return -1;
+
+       /* Perform the underlying seek operation. */
+       if (f->seek(f, off, whence) < 0) return -1;
+
+       /* If seek succeeded, file is seekable and we discard read buffer. */
+       f->rpos = f->rend = f->rstop = 0;
+       f->flags &= ~F_EOF;
+       
+       FUNLOCK(f);     
+       return 0;
+}
+
+int __fseeko(FILE *f, off_t off, int whence)
+{
+       int result;
+       FLOCK(f);
+       result = __fseeko_unlocked(f, off, whence);
+       FUNLOCK(f);
+       return result;
+}
+
+int fseek(FILE *f, long off, int whence)
+{
+       return __fseeko(f, off, whence);
+}
+
+weak_alias(__fseeko, fseeko);
+
+LFS64(fseeko);
diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c
new file mode 100644 (file)
index 0000000..5d76c8c
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+int fsetpos(FILE *f, const fpos_t *pos)
+{
+       return __fseeko(f, *(const off_t *)pos, SEEK_SET);
+}
+
+LFS64(fsetpos);
diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c
new file mode 100644 (file)
index 0000000..aa1f538
--- /dev/null
@@ -0,0 +1,35 @@
+#include "stdio_impl.h"
+
+off_t __ftello_unlocked(FILE *f)
+{
+       off_t pos = f->seek(f, 0, SEEK_CUR);
+       if (pos < 0) {
+               FUNLOCK(f);
+               return pos;
+       }
+       /* Adjust for data in buffer. */
+       return pos - (f->rend - f->rpos) + (f->wpos - f->wbase);
+}
+
+off_t __ftello(FILE *f)
+{
+       off_t pos;
+       FLOCK(f);
+       pos = __ftello_unlocked(f);
+       FUNLOCK(f);
+       return pos;
+}
+
+long ftell(FILE *f)
+{
+       off_t pos = __ftello(f);
+       if (pos > LONG_MAX) {
+               errno = EOVERFLOW;
+               return -1;
+       }
+       return pos;
+}
+
+weak_alias(__ftello, ftello);
+
+LFS64(ftello);
diff --git a/src/stdio/fwide.c b/src/stdio/fwide.c
new file mode 100644 (file)
index 0000000..f4da47f
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+#define SH (8*sizeof(int)-1)
+#define NORMALIZE(x) ((x)>>SH | -((-(x))>>SH))
+
+int fwide(FILE *f, int mode)
+{
+       if (!f->mode) f->mode = NORMALIZE(mode);
+       return f->mode;
+}
diff --git a/src/stdio/fwrite.c b/src/stdio/fwrite.c
new file mode 100644 (file)
index 0000000..23974fe
--- /dev/null
@@ -0,0 +1,51 @@
+#include "stdio_impl.h"
+
+size_t __fwritex(const unsigned char *s, size_t l, FILE *f)
+{
+       size_t i = 0;
+       size_t k = f->wend - f->wpos;
+
+       /* Handle line-buffered mode by breaking into 2 parts */
+       if (f->lbf >= 0) {
+               /* Match /^(.*\n|)/ */
+               for (i=l; i && s[i-1] != '\n'; i--);
+               if (i) {
+                       f->lbf = EOF;
+                       __fwritex(s, i, f);
+                       f->lbf = '\n';
+                       __oflow(f);
+                       return ferror(f) ? 0 : i + __fwritex(s+i, l-i, f);
+               }
+       }
+
+       /* Buffer initial segment */
+       if (k > l) k = l;
+       memcpy(f->wpos, s, k);
+       f->wpos += k;
+       if (f->wpos < f->wend) return l;
+
+       /* If there's work left to do, flush buffer */
+       __oflow(f);
+       if (ferror(f)) return 0;
+
+       /* If the remainder will not fit in buffer, write it directly */
+       if (l - k >= f->wend - f->wpos)
+               return k + f->write(f, s+k, l-k);
+
+       /* Otherwise, buffer the remainder */
+       memcpy(f->wpos, s+k, l-k);
+       f->wpos += l-k;
+       return l;
+}
+
+size_t fwrite(const void *src, size_t size, size_t nmemb, FILE *f)
+{
+       size_t l = size*nmemb;
+       if (!l) return l;
+       FLOCK(f);
+       l = __fwritex(src, l, f);
+       FUNLOCK(f);
+       return l/size;
+}
+
+weak_alias(fwrite, fwrite_unlocked);
diff --git a/src/stdio/fwscanf.c b/src/stdio/fwscanf.c
new file mode 100644 (file)
index 0000000..a6892cf
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int fwscanf(FILE *f, const wchar_t *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vfwscanf(f, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/getc.c b/src/stdio/getc.c
new file mode 100644 (file)
index 0000000..b739b0a
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+int getc(FILE *f)
+{
+       return fgetc(f);
+}
diff --git a/src/stdio/getc_unlocked.c b/src/stdio/getc_unlocked.c
new file mode 100644 (file)
index 0000000..629223e
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+int getc_unlocked(FILE *f)
+{
+       return f->rpos < f->rstop ? *f->rpos++ : __uflow(f);
+}
+
+weak_alias (getc_unlocked, fgetc_unlocked);
diff --git a/src/stdio/getchar.c b/src/stdio/getchar.c
new file mode 100644 (file)
index 0000000..c101265
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int getchar(void)
+{
+       return fgetc(stdin);
+}
diff --git a/src/stdio/getchar_unlocked.c b/src/stdio/getchar_unlocked.c
new file mode 100644 (file)
index 0000000..299cb95
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+int getchar_unlocked(void)
+{
+       return stdin->rpos < stdin->rstop ? *stdin->rpos++ : __uflow(stdin);
+}
diff --git a/src/stdio/getdelim.c b/src/stdio/getdelim.c
new file mode 100644 (file)
index 0000000..f770d20
--- /dev/null
@@ -0,0 +1,59 @@
+#include "stdio_impl.h"
+
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+
+ssize_t getdelim(char **s, size_t *n, int delim, FILE *f)
+{
+       char *tmp;
+       unsigned char *z;
+       size_t k;
+       size_t i=0;
+
+       if (!n || !s) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (!*s) *n=0;
+
+       FLOCK(f);
+
+       while (!feof(f)) {
+               z = memchr(f->rpos, delim, f->rend - f->rpos);
+               k = z ? z - f->rpos + 1 : f->rend - f->rpos;
+               if (i+k >= *n) {
+                       if (k >= SIZE_MAX-i) goto oom;
+                       *n = i+k+1;
+                       if (*n < SIZE_MAX/2) *n *= 2;
+                       tmp = realloc(*s, *n);
+                       if (!tmp) {
+                               *n = i+k+1;
+                               tmp = realloc(*s, *n);
+                               if (!tmp) goto oom;
+                       }
+                       *s = tmp;
+               }
+               memcpy(*s+i, f->rpos, k);
+               f->rpos += k;
+               i += k;
+               if (z) break;
+               __underflow(f);
+       }
+       (*s)[i] = 0;
+       if (feof(f) || ferror(f)) {
+               FUNLOCK(f);
+               return -1;
+       }
+
+       FUNLOCK(f);
+
+       if (i > SSIZE_MAX) {
+               errno = EOVERFLOW;
+               return -1;
+       }
+
+       return i;
+oom:
+       errno = ENOMEM;
+       return -1;
+}
diff --git a/src/stdio/getline.c b/src/stdio/getline.c
new file mode 100644 (file)
index 0000000..a3a6651
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+ssize_t getline(char **s, size_t *n, FILE *f)
+{
+       return getdelim(s, n, '\n', f);
+}
diff --git a/src/stdio/gets.c b/src/stdio/gets.c
new file mode 100644 (file)
index 0000000..24319eb
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+char *gets(char *s)
+{
+       char *ret = fgets(s, INT_MAX, stdin);
+       if (ret && s[strlen(s)-1] == '\n') s[strlen(s)-1] = 0;
+       return ret;
+}
diff --git a/src/stdio/getw.c b/src/stdio/getw.c
new file mode 100644 (file)
index 0000000..de9e985
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int getw(FILE *f)
+{
+       int x;
+       return fread(&x, sizeof x, 1, f) ? x : EOF;
+}
diff --git a/src/stdio/getwc.c b/src/stdio/getwc.c
new file mode 100644 (file)
index 0000000..a2818bc
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+wint_t getwc(FILE *f)
+{
+       return fgetwc(f);
+}
diff --git a/src/stdio/getwchar.c b/src/stdio/getwchar.c
new file mode 100644 (file)
index 0000000..2295bd4
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+wint_t getwchar(void)
+{
+       return fgetwc(stdin);
+}
+
+weak_alias(getwchar, getwchar_unlocked);
diff --git a/src/stdio/pclose.c b/src/stdio/pclose.c
new file mode 100644 (file)
index 0000000..c2fe7a2
--- /dev/null
@@ -0,0 +1,10 @@
+#include "stdio_impl.h"
+
+int pclose(FILE *f)
+{
+       int status;
+       fclose(f);
+       while (waitpid(f->pipe_pid, &status, 0) == -1)
+               if (errno != EINTR) return -1;
+       return status;
+}
diff --git a/src/stdio/perror.c b/src/stdio/perror.c
new file mode 100644 (file)
index 0000000..e4637c8
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "stdio_impl.h"
+
+void perror(const char *msg)
+{
+#if 1
+       if (msg) fprintf(stderr, "%s: %m\n", msg, strerror(errno));
+       else fprintf(stderr, "%m\n");
+#else
+       FILE *f = stderr;
+       char *errstr = strerror(errno);
+
+       FLOCK(f);
+       
+       if (msg) {
+               __fwritex(msg, strlen(msg), f);
+               __putc_unlocked(':', f);
+               __putc_unlocked(' ', f);
+       }
+       __fwritex(errstr, strlen(errstr), f);
+       __putc_unlocked('\n', f);
+
+       FUNLOCK(f);
+#endif
+}
diff --git a/src/stdio/popen.c b/src/stdio/popen.c
new file mode 100644 (file)
index 0000000..1d33e9d
--- /dev/null
@@ -0,0 +1,43 @@
+#include "stdio_impl.h"
+
+FILE *popen(const char *cmd, const char *mode)
+{
+       int p[2];
+       int op;
+       pid_t pid;
+       FILE *f;
+       const char *modes = "rw", *mi = strchr(modes, *mode);
+
+       if (mi) {
+               op = mi-modes;
+       } else {
+               errno = EINVAL;
+               return 0;
+       }
+       
+       if (pipe(p)) return NULL;
+       f = fdopen(p[op], mode);
+       if (!f) {
+               close(p[0]);
+               close(p[1]);
+               return NULL;
+       }
+       
+       pid = fork();
+       switch (pid) {
+       case -1:
+               fclose(f);
+               close(p[0]);
+               close(p[1]);
+               return NULL;
+       case 0:
+               dup2(p[1-op], 1-op);
+               close(p[0]);
+               close(p[1]);
+               execl("/bin/sh", "sh", "-c", cmd, (char *)0);
+               _exit(127);
+       }
+       close(p[1-op]);
+       f->pipe_pid = pid;
+       return f;
+}
diff --git a/src/stdio/printf.c b/src/stdio/printf.c
new file mode 100644 (file)
index 0000000..efeb8b3
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int printf(const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vprintf(fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/putc.c b/src/stdio/putc.c
new file mode 100644 (file)
index 0000000..3c9dc11
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+int putc(int c, FILE *f)
+{
+       return fputc(c, f);
+}
+
+weak_alias(putc, _IO_putc);
diff --git a/src/stdio/putc_unlocked.c b/src/stdio/putc_unlocked.c
new file mode 100644 (file)
index 0000000..f01da71
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+int putc_unlocked(int c, FILE *f)
+{
+       return f->wpos < f->wstop ? (*f->wpos++ = c) : __overflow(f, c);
+}
+
+weak_alias(putc_unlocked, fputc_unlocked);
diff --git a/src/stdio/putchar.c b/src/stdio/putchar.c
new file mode 100644 (file)
index 0000000..945636d
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int putchar(int c)
+{
+       return fputc(c, stdout);
+}
diff --git a/src/stdio/putchar_unlocked.c b/src/stdio/putchar_unlocked.c
new file mode 100644 (file)
index 0000000..72d47d1
--- /dev/null
@@ -0,0 +1,7 @@
+#include "stdio_impl.h"
+
+int putchar_unlocked(int c)
+{
+       return stdout->wpos < stdout->wstop ?
+               (*stdout->wpos++ = c) : __overflow(stdout, c);
+}
diff --git a/src/stdio/puts.c b/src/stdio/puts.c
new file mode 100644 (file)
index 0000000..eb70efd
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+int puts(const char *s)
+{
+       return -(fputs(s, stdout) < 0 || putchar('\n') < 0);
+}
diff --git a/src/stdio/putw.c b/src/stdio/putw.c
new file mode 100644 (file)
index 0000000..137832e
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int putw(int x, FILE *f)
+{
+       return fwrite(&x, sizeof x, 1, f) ? x : EOF;
+}
diff --git a/src/stdio/putwc.c b/src/stdio/putwc.c
new file mode 100644 (file)
index 0000000..80b54a4
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+wint_t putwc(wchar_t c, FILE *f)
+{
+       return fputwc(c, f);
+}
diff --git a/src/stdio/putwchar.c b/src/stdio/putwchar.c
new file mode 100644 (file)
index 0000000..3aacc1c
--- /dev/null
@@ -0,0 +1,8 @@
+#include "stdio_impl.h"
+
+wint_t putwchar(wchar_t c)
+{
+       return fputwc(c, stdout);
+}
+
+weak_alias(putwchar, putwchar_unlocked);
diff --git a/src/stdio/remove.c b/src/stdio/remove.c
new file mode 100644 (file)
index 0000000..8e33827
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "syscall.h"
+
+int remove(const char *path)
+{
+       return __syscall_unlink(path);
+}
diff --git a/src/stdio/rename.c b/src/stdio/rename.c
new file mode 100644 (file)
index 0000000..4eced08
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "syscall.h"
+
+int rename(const char *old, const char *new)
+{
+       return syscall2(__NR_rename, (long)old, (long)new);
+}
diff --git a/src/stdio/rewind.c b/src/stdio/rewind.c
new file mode 100644 (file)
index 0000000..7944b43
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void rewind(FILE *f)
+{
+       fseek(f, 0, SEEK_SET);
+}
diff --git a/src/stdio/scanf.c b/src/stdio/scanf.c
new file mode 100644 (file)
index 0000000..a04a440
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int scanf(const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vscanf(fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/setbuf.c b/src/stdio/setbuf.c
new file mode 100644 (file)
index 0000000..205afcf
--- /dev/null
@@ -0,0 +1,6 @@
+#include "stdio_impl.h"
+
+void setbuf(FILE *f, char *buf)
+{
+       setvbuf(f, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/src/stdio/setvbuf.c b/src/stdio/setvbuf.c
new file mode 100644 (file)
index 0000000..2985d3f
--- /dev/null
@@ -0,0 +1,22 @@
+#include "stdio_impl.h"
+
+/* This function makes no attempt to protect the user from his/her own
+ * stupidity. If called any time but when then ISO C standard specifically
+ * allows it, all hell can and will break loose, especially with threads!
+ *
+ * This implementation ignores all arguments except the buffering type,
+ * and uses the existing buffer allocated alongside the FILE object.
+ * In the case of stderr where the preexisting buffer is length 1, it
+ * is not possible to set line buffering or full buffering. */
+
+int setvbuf(FILE *f, char *buf, int type, size_t size)
+{
+       f->lbf = EOF;
+
+       if (type == _IONBF)
+               f->buf_size = 1;
+       else if (type == _IOLBF)
+               f->lbf = '\n';
+
+       return 0;
+}
diff --git a/src/stdio/snprintf.c b/src/stdio/snprintf.c
new file mode 100644 (file)
index 0000000..4071c2f
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int snprintf(char *s, size_t n, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vsnprintf(s, n, fmt, ap);
+       va_end(ap);
+       return ret;
+}
+
diff --git a/src/stdio/sprintf.c b/src/stdio/sprintf.c
new file mode 100644 (file)
index 0000000..6b22540
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int sprintf(char *s, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vsprintf(s, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/sscanf.c b/src/stdio/sscanf.c
new file mode 100644 (file)
index 0000000..a1cea69
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int sscanf(const char *s, const char *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vsscanf(s, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/stderr.c b/src/stdio/stderr.c
new file mode 100644 (file)
index 0000000..4a79d4e
--- /dev/null
@@ -0,0 +1,13 @@
+#include "stdio_impl.h"
+
+static unsigned char buf[1+UNGET];
+static FILE f = {
+       .buf = buf+UNGET,
+       .buf_size = 1,
+       .fd = 2,
+       .flags = F_PERM | F_NORD,
+       .write = __stdio_write,
+       .seek = __stdio_seek,
+       .close = __stdio_close,
+};
+FILE *const stderr = &f;
diff --git a/src/stdio/stdin.c b/src/stdio/stdin.c
new file mode 100644 (file)
index 0000000..51c9923
--- /dev/null
@@ -0,0 +1,13 @@
+#include "stdio_impl.h"
+
+static unsigned char buf[BUFSIZ+UNGET];
+static FILE f = {
+       .buf = buf+UNGET,
+       .buf_size = sizeof buf-UNGET,
+       .fd = 0,
+       .flags = F_PERM | F_NOWR,
+       .read = __stdio_read,
+       .seek = __stdio_seek,
+       .close = __stdio_close,
+};
+FILE *const stdin = &f;
diff --git a/src/stdio/stdout.c b/src/stdio/stdout.c
new file mode 100644 (file)
index 0000000..bf6eea6
--- /dev/null
@@ -0,0 +1,17 @@
+#include "stdio_impl.h"
+
+static unsigned char buf[BUFSIZ+UNGET];
+static FILE f = {
+       .buf = buf+UNGET,
+       .buf_size = sizeof buf-UNGET,
+       .fd = 1,
+       .flags = F_PERM | F_NORD,
+       .lbf = '\n',
+       .write = __stdio_write,
+       .seek = __stdio_seek,
+       .close = __stdio_close,
+};
+FILE *const stdout = &f;
+
+/* overrides symbol in fflush.c, used for flushing NULL */
+FILE *const __stdout_to_flush = &f;
diff --git a/src/stdio/swscanf.c b/src/stdio/swscanf.c
new file mode 100644 (file)
index 0000000..b66ad03
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int swscanf(const wchar_t *s, const wchar_t *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vswscanf(s, fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c
new file mode 100644 (file)
index 0000000..2cbcb86
--- /dev/null
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include "libc.h"
+
+char *tempnam(const char *dir, const char *pfx)
+{
+       static int lock;
+       static int index;
+       char *s;
+       int pid = getpid();
+       int l;
+
+       if (!dir) dir = P_tmpdir;
+       if (!pfx) pfx = "temp";
+
+       if (access(dir, R_OK|W_OK|X_OK) != 0)
+               return NULL;
+
+       l = strlen(dir) + 1 + strlen(pfx) + 2 + sizeof(int)*3*2 + 1;
+       s = malloc(l);
+       if (!s) {
+               errno = ENOMEM;
+               return NULL;
+       }
+
+       LOCK(&lock);
+       for (; index < TMP_MAX; index++) {
+               snprintf(s, l, "%s/%s-%d-%d", dir, pfx, pid, index);
+               if (access(s, F_OK) != 0) {
+                       UNLOCK(&lock);
+                       return s;
+               }
+       }
+       UNLOCK(&lock);
+       free(s);
+       return NULL;    
+}
diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c
new file mode 100644 (file)
index 0000000..185025f
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "stdio_impl.h"
+
+FILE *tmpfile(void)
+{
+       char buf[L_tmpnam], *s;
+       int fd;
+       FILE *f;
+       for (;;) {
+               s = tmpnam(buf);
+               if (!s) return NULL;
+               fd = __syscall_open(s, O_RDWR | O_CREAT | O_EXCL, 0600);
+               if (fd >= 0) {
+                       f = __fdopen(fd, "w+");
+                       remove(s);
+                       return f;
+               }
+       }
+}
+
+LFS64(tmpfile);
diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c
new file mode 100644 (file)
index 0000000..14d5922
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include "libc.h"
+
+char *tmpnam(char *s)
+{
+       static int lock;
+       static int index;
+       static char *s2;
+       int pid = getpid();
+       char *dir = getenv("TMPDIR");
+
+       if (!s) {
+               if (!s2) s2 = malloc(L_tmpnam);
+               s = s2;
+       }
+
+       /* this interface is insecure anyway but at least we can try.. */
+       if (!dir || strlen(dir) > L_tmpnam-32)
+               dir = P_tmpdir;
+
+       if (access(dir, R_OK|W_OK|X_OK) != 0)
+               return NULL;
+
+       LOCK(&lock);
+       for (index++; index < TMP_MAX; index++) {
+               snprintf(s, L_tmpnam, "%s/temp%d-%d", dir, pid, index);
+               if (access(s, F_OK) != 0) {
+                       UNLOCK(&lock);
+                       return s;
+               }
+       }
+       UNLOCK(&lock);
+       return NULL;
+}
diff --git a/src/stdio/ungetc.c b/src/stdio/ungetc.c
new file mode 100644 (file)
index 0000000..0718168
--- /dev/null
@@ -0,0 +1,33 @@
+#include "stdio_impl.h"
+
+int ungetc(int c, FILE *f)
+{
+       if (c == EOF) return c;
+
+       FLOCK(f);
+
+       /* Fail if unreadable or writing and unable to flush */
+       if ((f->flags & (F_ERR|F_NORD)) || (f->wpos && __oflow(f))) {
+               FUNLOCK(f);
+               return EOF;
+       }
+
+       /* Clear write mode */
+       f->wbase = f->wpos = f->wstop = f->wend = 0;
+
+       /* Put the file in read mode */
+       if (!f->rpos) f->rpos = f->rend = f->buf;
+
+       /* If unget buffer is already full, fail. */
+       if (f->rpos <= f->buf - UNGET) {
+               FUNLOCK(f);
+               return EOF;
+       }
+
+       /* Put a byte back into the buffer */
+       *--f->rpos = c;
+       f->flags &= ~F_EOF;
+
+       FUNLOCK(f);
+       return c;
+}
diff --git a/src/stdio/ungetwc.c b/src/stdio/ungetwc.c
new file mode 100644 (file)
index 0000000..f7cde2e
--- /dev/null
@@ -0,0 +1,45 @@
+#include "stdio_impl.h"
+
+wint_t ungetwc(wint_t c, FILE *f)
+{
+       unsigned char mbc[MB_LEN_MAX];
+       int l=1;
+
+       if (c == WEOF) return c;
+
+       /* Try conversion early so we can fail without locking if invalid */
+       if (!isascii(c) && (l = wctomb(mbc, c)) < 0)
+               return WEOF;
+
+       FLOCK(f);
+
+       f->mode |= f->mode+1;
+
+       /* Fail if unreadable or writing and unable to flush */
+       if ((f->flags & (F_ERR|F_NORD)) || (f->wpos && __oflow(f))) {
+               FUNLOCK(f);
+               return EOF;
+       }
+
+       /* Clear write mode */
+       f->wpos = f->wstop = f->wend = 0;
+
+       /* Put the file in read mode */
+       if (!f->rpos) f->rpos = f->rend = f->buf;
+
+       /* If unget buffer is nonempty, fail. */
+       if (f->rpos < f->buf) {
+               FUNLOCK(f);
+               return WEOF;
+       }
+
+       /* Put character back into the buffer */
+       if (isascii(c)) *--f->rpos = c;
+       else memcpy(f->rpos -= l, mbc, l);
+
+       /* Clear EOF */
+       f->flags &= ~F_EOF;
+
+       FUNLOCK(f);
+       return c;
+}
diff --git a/src/stdio/vasprintf.c b/src/stdio/vasprintf.c
new file mode 100644 (file)
index 0000000..f2bbc7a
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#define GUESS 240U
+
+int vasprintf(char **s, const char *fmt, va_list ap)
+{
+       va_list ap2;
+       char *a;
+       int l=GUESS;
+
+       if (!(a=malloc(GUESS))) return -1;
+
+       va_copy(ap2, ap);
+       l=vsnprintf(a, GUESS, fmt, ap2);
+       va_end(ap2);
+
+       if (l<GUESS) {
+               char *b = realloc(a, l+1U);
+               *s = b ? b : a;
+               return l;
+       }
+       free(a);
+       if (l<0 || !(*s=malloc(l+1U))) return -1;
+       return vsnprintf(*s, l+1U, fmt, ap);
+}
diff --git a/src/stdio/vdprintf.c b/src/stdio/vdprintf.c
new file mode 100644 (file)
index 0000000..bfb1b0a
--- /dev/null
@@ -0,0 +1,14 @@
+#include "stdio_impl.h"
+
+int vdprintf(int fd, const char *fmt, va_list ap)
+{
+       int r;
+       char buf[BUFSIZ];
+       FILE f = {
+               .fd = fd, .lbf = EOF, .write = __stdio_write,
+               .buf = buf+UNGET, .buf_size = sizeof buf - UNGET
+       };
+       r = vfprintf(&f, fmt, ap);
+       __oflow(&f);
+       return r;
+}
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
new file mode 100644 (file)
index 0000000..5e19acc
--- /dev/null
@@ -0,0 +1,640 @@
+#include "stdio_impl.h"
+
+/* Some useful macros */
+
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+#define CONCAT2(x,y) x ## y
+#define CONCAT(x,y) CONCAT2(x,y)
+
+/* Convenient bit representation for modifier flags, which all fall
+ * within 31 codepoints of the space character. */
+
+#define ALT_FORM   (1U<<'#'-' ')
+#define ZERO_PAD   (1U<<'0'-' ')
+#define LEFT_ADJ   (1U<<'-'-' ')
+#define PAD_POS    (1U<<' '-' ')
+#define MARK_POS   (1U<<'+'-' ')
+#define GROUPED    (1U<<'\''-' ')
+
+#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
+
+#if UINT_MAX == ULONG_MAX
+#define LONG_IS_INT
+#endif
+
+#if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX
+#define ODD_TYPES
+#endif
+
+/* State machine to accept length modifiers + conversion specifiers.
+ * Result is 0 on failure, or an argument type to pop on success. */
+
+enum {
+       BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
+       ZTPRE, JPRE,
+       STOP,
+       PTR, INT, UINT, ULLONG,
+#ifndef LONG_IS_INT
+       LONG, ULONG,
+#else
+#define LONG INT
+#define ULONG UINT
+#endif
+       SHORT, USHORT, CHAR, UCHAR,
+#ifdef ODD_TYPES
+       LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
+#else
+#define LLONG ULLONG
+#define SIZET ULONG
+#define IMAX LLONG
+#define UMAX ULLONG
+#define PDIFF LONG
+#define UIPTR ULONG
+#endif
+       DBL, LDBL,
+       NOARG,
+       MAXSTATE
+};
+
+#define S(x) [(x)-'A']
+
+static const unsigned char states[]['z'-'A'+1] = {
+       { /* 0: bare types */
+               S('d') = INT, S('i') = INT,
+               S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
+               S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
+               S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
+               S('c') = CHAR, S('C') = INT,
+               S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
+               S('m') = NOARG,
+               S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
+               S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
+       }, { /* 1: l-prefixed */
+               S('d') = LONG, S('i') = LONG,
+               S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
+               S('c') = INT, S('s') = PTR, S('n') = PTR,
+               S('l') = LLPRE,
+       }, { /* 2: ll-prefixed */
+               S('d') = LLONG, S('i') = LLONG,
+               S('o') = ULLONG, S('u') = ULLONG,
+               S('x') = ULLONG, S('X') = ULLONG,
+               S('n') = PTR,
+       }, { /* 3: h-prefixed */
+               S('d') = SHORT, S('i') = SHORT,
+               S('o') = USHORT, S('u') = USHORT,
+               S('x') = USHORT, S('X') = USHORT,
+               S('n') = PTR,
+               S('h') = HHPRE,
+       }, { /* 4: hh-prefixed */
+               S('d') = CHAR, S('i') = CHAR,
+               S('o') = UCHAR, S('u') = UCHAR,
+               S('x') = UCHAR, S('X') = UCHAR,
+               S('n') = PTR,
+       }, { /* 5: L-prefixed */
+               S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
+               S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
+               S('n') = PTR,
+       }, { /* 6: z- or t-prefixed (assumed to be same size) */
+               S('d') = PDIFF, S('i') = PDIFF,
+               S('o') = SIZET, S('u') = SIZET,
+               S('x') = SIZET, S('X') = SIZET,
+               S('n') = PTR,
+       }, { /* 7: j-prefixed */
+               S('d') = IMAX, S('i') = IMAX,
+               S('o') = UMAX, S('u') = UMAX,
+               S('x') = UMAX, S('X') = UMAX,
+               S('n') = PTR,
+       }
+};
+
+#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
+
+union arg
+{
+       uintmax_t i;
+       long double f;
+       void *p;
+};
+
+static void pop_arg(union arg *arg, int type, va_list *ap)
+{
+       /* Give the compiler a hint for optimizing the switch. */
+       if ((unsigned)type > MAXSTATE) return;
+       switch (type) {
+              case PTR:        arg->p = va_arg(*ap, void *);
+       break; case INT:        arg->i = va_arg(*ap, int);
+       break; case UINT:       arg->i = va_arg(*ap, unsigned int);
+#ifndef LONG_IS_INT
+       break; case LONG:       arg->i = va_arg(*ap, long);
+       break; case ULONG:      arg->i = va_arg(*ap, unsigned long);
+#endif
+       break; case ULLONG:     arg->i = va_arg(*ap, unsigned long long);
+       break; case SHORT:      arg->i = (short)va_arg(*ap, int);
+       break; case USHORT:     arg->i = (unsigned short)va_arg(*ap, int);
+       break; case CHAR:       arg->i = (signed char)va_arg(*ap, int);
+       break; case UCHAR:      arg->i = (unsigned char)va_arg(*ap, int);
+#ifdef ODD_TYPES
+       break; case LLONG:      arg->i = va_arg(*ap, long long);
+       break; case SIZET:      arg->i = va_arg(*ap, size_t);
+       break; case IMAX:       arg->i = va_arg(*ap, intmax_t);
+       break; case UMAX:       arg->i = va_arg(*ap, uintmax_t);
+       break; case PDIFF:      arg->i = va_arg(*ap, ptrdiff_t);
+       break; case UIPTR:      arg->i = (uintptr_t)va_arg(*ap, void *);
+#endif
+       break; case DBL:        arg->f = va_arg(*ap, double);
+       break; case LDBL:       arg->f = va_arg(*ap, long double);
+       }
+}
+
+static void out(FILE *f, const char *s, size_t l)
+{
+       __fwritex(s, l, f);
+}
+
+static void pad(FILE *f, char c, int w, int l, int fl)
+{
+       char pad[256];
+       if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
+       l = w - l;
+       memset(pad, c, l>sizeof pad ? sizeof pad : l);
+       for (; l >= sizeof pad; l -= sizeof pad)
+               out(f, pad, sizeof pad);
+       out(f, pad, l);
+}
+
+static const char xdigits[16] = {
+       "0123456789ABCDEF"
+};
+
+static char *fmt_x(uintmax_t x, char *s, int lower)
+{
+       for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
+       return s;
+}
+
+static char *fmt_o(uintmax_t x, char *s)
+{
+       for (; x; x>>=3) *--s = '0' + (x&7);
+       return s;
+}
+
+static char *fmt_u(uintmax_t x, char *s)
+{
+       unsigned long y;
+       for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
+       for (y=x;           y; y/=10) *--s = '0' + y%10;
+       return s;
+}
+
+static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
+{
+       uint32_t big[(LDBL_MAX_EXP+LDBL_MANT_DIG)/9+1];
+       uint32_t *a, *d, *r, *z;
+       int e2=0, e, i, j, l;
+       char buf[9+LDBL_MANT_DIG/4], *s;
+       const char *prefix="-+ ";
+       int pl;
+       char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
+
+       pl=1;
+       if (y<0 || 1/y<0) {
+               y=-y;
+       } else if (fl & MARK_POS) {
+               prefix++;
+       } else if (fl & PAD_POS) {
+               prefix+=2;
+       } else pl=0;
+
+       if (!isfinite(y)) {
+               char *s = (t&32)?"inf":"INF";
+               if (y!=y) s=(t&32)?"nan":"NAN", pl=0;
+               pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
+               out(f, prefix, pl);
+               out(f, s, 3);
+               pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
+               return MAX(w, 3+pl);
+       }
+
+       y = frexpl(y, &e2) * 2;
+       if (y) e2--;
+
+       if ((t|32)=='a') {
+               long double round = 8.0;
+               int re;
+
+               if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0;
+               else re=LDBL_MANT_DIG/4-1-p;
+
+               if (re) {
+                       if (pl && *prefix=='-') y=-y;
+                       while (re--) round*=16;
+                       y+=round;
+                       y-=round;
+                       if (y<0) y=-y;
+               }
+
+               estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
+               if (estr==ebuf) *--estr='0';
+               *--estr = (e2<0 ? '-' : '+');
+               *--estr = t+('p'-'a');
+
+               s=buf;
+               *s++='0';
+               *s++=t+('x'-'a');
+               do {
+                       int x=y;
+                       *s++=xdigits[x]|(t&32);
+                       y=16*(y-x);
+                       if (s-buf==3 && (y||p>0||(fl&ALT_FORM))) *s++='.';
+               } while (y);
+
+               if (p<0) p = s-buf-4;
+               l = 1 + p + (p || (fl&ALT_FORM)) + ebuf-estr;
+
+               pad(f, ' ', w, pl+l, fl);
+               out(f, prefix, pl);
+               pad(f, '0', w, pl+l, fl^ZERO_PAD);
+               out(f, buf, s-buf);
+               pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
+               out(f, estr, ebuf-estr);
+               pad(f, '0', w, pl+l, fl^LEFT_ADJ);
+               return MAX(w, pl+l);
+       }
+       if (p<0) p=6;
+
+       y *= 0x1p28; e2-=28;
+
+       if (e2<0) a=r=z=big;
+       else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
+
+       do {
+               *z = y;
+               y = 1000000000*(y-*z++);
+       } while (y);
+
+       while (e2>0) {
+               uint32_t carry=0;
+               int sh=MIN(29,e2);
+               for (d=z-1; d>=a; d--) {
+                       uint64_t x = ((uint64_t)*d<<sh)+carry;
+                       *d = x % 1000000000;
+                       carry = x / 1000000000;
+               }
+               if (!z[-1] && z>a) z--;
+               if (carry) *--a = carry;
+               e2-=sh;
+       }
+       while (e2<0) {
+               uint32_t carry=0, *z2;
+               int sh=MIN(9,-e2);
+               for (d=a; d<z; d++) {
+                       uint32_t rm = *d & (1<<sh)-1;
+                       *d = (*d>>sh) + carry;
+                       carry = (1000000000>>sh) * rm;
+               }
+               if (!*a) a++;
+               if (carry) *z++ = carry;
+               /* Avoid (slow!) computation past requested precision */
+               z2 = ((t|32)=='f' ? r : a) + 2 + p/9;
+               z = MIN(z, z2);
+               e2+=sh;
+       }
+
+       if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
+       else e=0;
+
+       /* Perform rounding: j is precision after the radix (possibly neg) */
+       j = p - ((t|32)!='f')*e - ((t|32)=='g');
+       if (j < 9*(z-r-1)) {
+               uint32_t x;
+               /* We avoid C's broken division of negative numbers */
+               d = r + 1 + (j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP;
+               j += 9*LDBL_MAX_EXP;
+               j %= 9;
+               for (i=10, j++; j<9; i*=10, j++);
+               x = *d % i;
+               /* Are there any significant digits past j? */
+               if (x || d+1!=z) {
+                       long double round = CONCAT(0x1p,LDBL_MANT_DIG);
+                       long double small;
+                       if (x<i/2) small=0x01p-1;
+                       else if (i==i/2 && d+1==z) small=0x10p-1;
+                       else small=0x11p-1;
+                       if (pl && *prefix=='-') round*=-1, small*=-1;
+                       /* Decide whether to round by probing round+small */
+                       if (round+small != round) {
+                               *d = *d - x + i;
+                               while (*d > 999999999) {
+                                       *d--=0;
+                                       (*d)++;
+                               }
+                               if (d<a) a=d;
+                               for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
+                       }
+               }
+               for (; !z[-1] && z>a; z--);
+       }
+       
+       if ((t|32)=='g') {
+               if (!p) p++;
+               if (p>e && e>=-4) {
+                       t--;
+                       p-=e+1;
+               } else {
+                       t-=2;
+                       p--;
+               }
+               if (!(fl&ALT_FORM)) {
+                       /* Count trailing zeros in last place */
+                       if (z>a) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
+                       else j=9;
+                       if ((t|32)=='f')
+                               p = MIN(p,MAX(0,9*(z-r-1)-j));
+                       else
+                               p = MIN(p,MAX(0,9*(z-r-1)+e-j));
+               }
+       }
+       l = 1 + p + (p || (fl&ALT_FORM));
+       if ((t|32)=='f') {
+               if (e>0) l+=e;
+       } else {
+               estr=fmt_u(e<0 ? -e : e, ebuf);
+               while(ebuf-estr<2) *--estr='0';
+               *--estr = (e<0 ? '-' : '+');
+               *--estr = t;
+               l += ebuf-estr;
+       }
+
+       pad(f, ' ', w, pl+l, fl);
+       out(f, prefix, pl);
+       pad(f, '0', w, pl+l, fl^ZERO_PAD);
+
+       if ((t|32)=='f') {
+               if (a>r) a=r;
+               for (d=a; d<=r; d++) {
+                       char *s = fmt_u(*d, buf+9);
+                       if (d!=a) while (s>buf) *--s='0';
+                       else if (s==buf+9) *--s='0';
+                       out(f, s, buf+9-s);
+               }
+               if (p || (fl&ALT_FORM)) out(f, ".", 1);
+               for (; d<z && p>0; d++, p-=9) {
+                       char *s = fmt_u(*d, buf+9);
+                       while (s>buf) *--s='0';
+                       out(f, s, MIN(9,p));
+               }
+               pad(f, '0', p+9, 9, 0);
+       } else {
+               if (z<=a) z=a+1;
+               for (d=a; d<z && p>=0; d++) {
+                       char *s = fmt_u(*d, buf+9);
+                       if (s==buf+9) *--s='0';
+                       if (d!=a) while (s>buf) *--s='0';
+                       else {
+                               out(f, s++, 1);
+                               if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
+                       }
+                       out(f, s, MIN(buf+9-s, p));
+                       p -= buf+9-s;
+               }
+               pad(f, '0', p+18, 18, 0);
+               out(f, estr, ebuf-estr);
+       }
+
+       pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
+
+       return MAX(w, pl+l);
+}
+
+static int getint(char **s) {
+       int i;
+       for (i=0; isdigit(**s); (*s)++)
+               i = 10*i + (**s-'0');
+       return i;
+}
+
+static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
+{
+       char *a, *z, *s=(char *)fmt;
+       unsigned l10n=0, litpct, fl;
+       int w, p;
+       union arg arg;
+       int argpos;
+       unsigned st, ps;
+       int cnt=0, l=0;
+       int i;
+       char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
+       const char *prefix;
+       int t, pl;
+       wchar_t wc[2], *ws;
+       char mb[4];
+
+       for (;;) {
+               /* Update output count, end loop when fmt is exhausted */
+               if (cnt >= 0) {
+                       if (l > INT_MAX - cnt) {
+                               if (!ferror(f)) errno = EOVERFLOW;
+                               cnt = -1;
+                       } else cnt += l;
+               }
+               if (!*s) break;
+
+               /* Handle literal text and %% format specifiers */
+               for (a=s; *s && *s!='%'; s++);
+               litpct = strspn(s, "%")/2; /* Optimize %%%% runs */
+               z = s+litpct;
+               s += 2*litpct;
+               l = z-a;
+               if (f) out(f, a, l);
+               if (l) continue;
+
+               if (isdigit(s[1]) && s[2]=='$') {
+                       l10n=1;
+                       argpos = s[1]-'0';
+                       s+=3;
+               } else {
+                       argpos = -1;
+                       s++;
+               }
+
+               /* Read modifier flags */
+               for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
+                       fl |= 1U<<*s-' ';
+
+               /* Read field width */
+               if (*s=='*') {
+                       if (isdigit(s[1]) && s[2]=='$') {
+                               l10n=1;
+                               nl_type[s[1]-'0'] = INT;
+                               w = nl_arg[s[1]-'0'].i;
+                               s+=3;
+                       } else if (!l10n) {
+                               w = f ? va_arg(*ap, int) : 0;
+                               s++;
+                       } else return -1;
+                       if (w<0) fl|=LEFT_ADJ, w=-w;
+               } else if ((w=getint(&s))<0) return -1;
+
+               /* Read precision */
+               if (*s=='.' && s[1]=='*') {
+                       if (isdigit(s[2]) && s[3]=='$') {
+                               nl_type[s[2]-'0'] = INT;
+                               p = nl_arg[s[2]-'0'].i;
+                               s+=4;
+                       } else if (!l10n) {
+                               p = f ? va_arg(*ap, int) : 0;
+                               s+=2;
+                       } else return -1;
+               } else if (*s=='.') {
+                       s++;
+                       p = getint(&s);
+               } else p = -1;
+
+               /* Format specifier state machine */
+               st=0;
+               do {
+                       if (OOB(*s)) return -1;
+                       ps=st;
+                       st=states[st]S(*s++);
+               } while (st-1<STOP);
+               if (!st) return -1;
+
+               /* Check validity of argument type (nl/normal) */
+               if (st==NOARG) {
+                       if (argpos>=0) return -1;
+                       else if (!f) continue;
+               } else {
+                       if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
+                       else if (f) pop_arg(&arg, st, ap);
+                       else return 0;
+               }
+
+               if (!f) continue;
+
+               z = buf + sizeof(buf);
+               prefix = "-+   0X0x";
+               pl = 0;
+               t = s[-1];
+
+               /* Transform ls,lc -> S,C */
+               if (ps && (t&15)==3) t&=~32;
+
+               /* - and 0 flags are mutually exclusive */
+               if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
+
+               switch(t) {
+               case 'n':
+                       switch(ps) {
+                       case BARE: *(int *)arg.p = l;
+                       case LPRE: *(long *)arg.p = l;
+                       case LLPRE: *(long long *)arg.p = l;
+                       case HPRE: *(unsigned short *)arg.p = l;
+                       case HHPRE: *(unsigned char *)arg.p = l;
+                       case ZTPRE: *(size_t *)arg.p = l;
+                       case JPRE: *(uintmax_t *)arg.p = l;
+                       }
+                       continue;
+               case 'p':
+                       p = MAX(p, 2*sizeof(void*));
+                       t = 'x';
+                       fl |= ALT_FORM;
+               case 'x': case 'X':
+                       a = fmt_x(arg.i, z, t&32);
+                       if (fl & ALT_FORM) prefix+=(t>>4), pl=2;
+                       if (0) {
+               case 'o':
+                       a = fmt_o(arg.i, z);
+                       if ((fl&ALT_FORM) && arg.i) prefix+=5, pl=1;
+                       } if (0) {
+               case 'd': case 'i':
+                       pl=1;
+                       if (arg.i>INTMAX_MAX) {
+                               arg.i=-arg.i;
+                       } else if (fl & MARK_POS) {
+                               prefix++;
+                       } else if (fl & PAD_POS) {
+                               prefix+=2;
+                       } else pl=0;
+               case 'u':
+                       a = fmt_u(arg.i, z);
+                       }
+                       if (!arg.i && !p) continue;
+                       if (p>=0) fl &= ~ZERO_PAD;
+                       p = MAX(p, z-a + !arg.i);
+                       break;
+               case 'c':
+                       *(a=z-(p=1))=arg.i;
+                       fl &= ~ZERO_PAD;
+                       break;
+               case 'm':
+                       if (1) a = strerror(errno); else
+               case 's':
+                       a = arg.p;
+                       z = memchr(a, 0, p);
+                       if (!z) z=a+p;
+                       else p=z-a;
+                       fl &= ~ZERO_PAD;
+                       break;
+               case 'C':
+                       wc[0] = arg.i;
+                       wc[1] = 0;
+                       arg.p = wc;
+                       p = -1;
+               case 'S':
+                       ws = arg.p;
+                       for (i=0; *ws && (l=wctomb(mb, *ws++))>=0 && l<=0U+p-i; i+=l);
+                       if (l<0) return -1;
+                       p = i;
+                       pad(f, ' ', w, p, fl);
+                       ws = arg.p;
+                       for (i=0; *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l)
+                               out(f, mb, l);
+                       pad(f, ' ', w, p, fl^LEFT_ADJ);
+                       l = w>p ? w : p;
+                       continue;
+               case 'e': case 'f': case 'g': case 'a':
+               case 'E': case 'F': case 'G': case 'A':
+                       l = fmt_fp(f, arg.f, w, p, fl, t);
+                       continue;
+               }
+
+               if (p < z-a) p = z-a;
+               if (w < pl+p) w = pl+p;
+
+               pad(f, ' ', w, pl+p, fl);
+               out(f, prefix, pl);
+               pad(f, '0', w, pl+p, fl^ZERO_PAD);
+               pad(f, '0', p, z-a, 0);
+               out(f, a, z-a);
+               pad(f, ' ', w, pl+p, fl^LEFT_ADJ);
+
+               l = w;
+       }
+
+       if (f) return cnt;
+       if (!l10n) return 0;
+
+       for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
+               pop_arg(nl_arg+i, nl_type[i], ap);
+       for (; i<=NL_ARGMAX && !nl_type[i]; i++);
+       if (i<=NL_ARGMAX) return -1;
+       return 1;
+}
+
+int vfprintf(FILE *f, const char *fmt, va_list ap)
+{
+       va_list ap2;
+       int nl_type[NL_ARGMAX] = {0};
+       union arg nl_arg[NL_ARGMAX];
+       int ret;
+
+       va_copy(ap2, ap);
+       if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) return -1;
+
+       FLOCK(f);
+       ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
+       FUNLOCK(f);
+       va_end(ap2);
+       return ret;
+}
diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c
new file mode 100644 (file)
index 0000000..69f4508
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "stdio_impl.h"
+#include "__scanf.h"
+
+static void f_read(rctx_t *r)
+{
+       FILE *f = r->opaque;
+       if ((r->c = __uflow(f)) >= 0) r->l++;
+}
+
+int vfscanf(FILE *f, const char *fmt, va_list ap)
+{
+       size_t l = strlen(fmt), i, result;
+       rctx_t r = { f_read, (void *)f, 0, isspace };
+       wchar_t fmt2[l+1];
+
+       if (l > 0x100000) {
+               errno = ENOMEM;
+               return -1;
+       }
+       for (i=0; i<=l; i++) fmt2[i] = (unsigned char)fmt[i];
+
+       FLOCK(f);
+
+       result = __scanf(&r, fmt2, ap);
+
+       if (r.u && r.c >= 0) {
+               /* This code takes care of the case where the caller performs
+                * a nonmatching scanf to leave a character in the unscan
+                * buffer, followed by an unget, followed by a scanf that
+                * matches zero characters. In this case the final 'unread'
+                * character must be returned to the unget buffer rather than
+                * the unscan buffer. */
+                f->rpos--;
+       }
+
+       FUNLOCK(f);
+       return result;
+}
diff --git a/src/stdio/vfwscanf.c b/src/stdio/vfwscanf.c
new file mode 100644 (file)
index 0000000..491c140
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "stdio_impl.h"
+#include "__scanf.h"
+
+static void f_read(rctx_t *r)
+{
+       FILE *f = r->opaque;
+       if ((r->c = fgetwc(f)) >= 0) r->l++;
+}
+
+int vfwscanf(FILE *f, const wchar_t *fmt, va_list ap)
+{
+       rctx_t r = { f_read, (void *)f, 1, iswspace };
+       int result;
+
+       result = __scanf(&r, fmt, ap);
+
+       if (r.u && r.c >= 0) {
+               ungetwc(r.c, f);
+       }
+
+       return result;
+}
diff --git a/src/stdio/vprintf.c b/src/stdio/vprintf.c
new file mode 100644 (file)
index 0000000..67b38da
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int vprintf(const char *fmt, va_list ap)
+{
+       return vfprintf(stdout, fmt, ap);
+}
diff --git a/src/stdio/vscanf.c b/src/stdio/vscanf.c
new file mode 100644 (file)
index 0000000..6f55b1c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int vscanf(const char *fmt, va_list ap)
+{
+       return vfscanf(stdin, fmt, ap);
+}
diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c
new file mode 100644 (file)
index 0000000..bda6b49
--- /dev/null
@@ -0,0 +1,33 @@
+#include "stdio_impl.h"
+
+static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
+{
+       /* pretend to succeed, but discard data */
+       return l;
+}
+
+int vsnprintf(char *s, size_t n, const char *fmt, va_list ap)
+{
+       int r;
+       FILE f;
+       unsigned char buf[1];
+
+       memset(&f, 0, sizeof(FILE));
+       f.lbf = EOF;
+       f.write = sn_write;
+       f.buf_size = 1;
+       f.buf = buf;
+       if (n > INT_MAX) {
+               errno = EOVERFLOW;
+               return -1;
+       } else if (n > 0) {
+               if (n > (char *)0+SIZE_MAX-s) n = (char *)0+SIZE_MAX-s;
+               f.wpos = s;
+               f.wbase = f.wend = s+n-1;
+               f.wstop = f.wend - 1;
+       }
+       r = vfprintf(&f, fmt, ap);
+       /* wpos points just after last byte written, or to s+n-1 (wbase) */
+       *f.wpos = 0;
+       return r;
+}
diff --git a/src/stdio/vsprintf.c b/src/stdio/vsprintf.c
new file mode 100644 (file)
index 0000000..7836ccb
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <limits.h>
+
+int vsprintf(char *s, const char *fmt, va_list ap)
+{
+       return vsnprintf(s, INT_MAX, fmt, ap);
+}
diff --git a/src/stdio/vsscanf.c b/src/stdio/vsscanf.c
new file mode 100644 (file)
index 0000000..fd48f70
--- /dev/null
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "__scanf.h"
+
+static void s_read(rctx_t *r)
+{
+       unsigned char *s = r->opaque;
+       if (!s[r->l]) r->c = -1;
+       else r->c = s[r->l++];
+}
+
+int vsscanf(const char *s, const char *fmt, va_list ap)
+{
+       size_t l = strlen(fmt), i;
+       wchar_t fmt2[l+1];
+       rctx_t r = { s_read, (void *)s, 0, isspace };
+       for (i=0; i<=l; i++) fmt2[i] = (unsigned char)fmt[i];
+       return __scanf(&r, fmt2, ap);
+}
diff --git a/src/stdio/vswscanf.c b/src/stdio/vswscanf.c
new file mode 100644 (file)
index 0000000..2c4ffbe
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "__scanf.h"
+
+static void s_read(rctx_t *r)
+{
+       wchar_t *s = r->opaque;
+       if (!s[r->l]) r->c = -1;
+       else r->c = s[r->l++];
+}
+
+int vswscanf(const wchar_t *s, const wchar_t *fmt, va_list ap)
+{
+       rctx_t r = { s_read, (void *)s, 1, iswspace };
+       return __scanf(&r, fmt, ap);
+}
diff --git a/src/stdio/vwscanf.c b/src/stdio/vwscanf.c
new file mode 100644 (file)
index 0000000..86da045
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int vwscanf(const wchar_t *fmt, va_list ap)
+{
+       return vfwscanf(stdin, fmt, ap);
+}
diff --git a/src/stdio/wscanf.c b/src/stdio/wscanf.c
new file mode 100644 (file)
index 0000000..34b5884
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+int wscanf(const wchar_t *fmt, ...)
+{
+       int ret;
+       va_list ap;
+       va_start(ap, fmt);
+       ret = vwscanf(fmt, ap);
+       va_end(ap);
+       return ret;
+}
diff --git a/src/stdlib/abs.c b/src/stdlib/abs.c
new file mode 100644 (file)
index 0000000..4806d62
--- /dev/null
@@ -0,0 +1,4 @@
+int abs(int a)
+{
+       return a>0 ? a : -a;
+}
diff --git a/src/stdlib/atof.c b/src/stdlib/atof.c
new file mode 100644 (file)
index 0000000..f7fcd82
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+double atof(const char *s)
+{
+       return strtod(s, 0);
+}
diff --git a/src/stdlib/atoi.c b/src/stdlib/atoi.c
new file mode 100644 (file)
index 0000000..648b154
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+#include <ctype.h>
+
+int atoi(const char *s)
+{
+       int n=0, neg=0;
+       while (isspace(*s)) s++;
+       switch (*s) {
+       case '-': neg=1;
+       case '+': s++;
+       }
+       while (isdigit(*s))
+               n = 10*n + *s++ - '0';
+       return neg ? -n : n;
+}
diff --git a/src/stdlib/atol.c b/src/stdlib/atol.c
new file mode 100644 (file)
index 0000000..9c91bba
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdlib.h>
+#include <ctype.h>
+
+long atol(const char *s)
+{
+       long n=0;
+       int neg=0;
+       while (isspace(*s)) s++;
+       switch (*s) {
+       case '-': neg=1;
+       case '+': s++;
+       }
+       while (isdigit(*s))
+               n = 10*n + *s++ - '0';
+       return neg ? -n : n;
+}
diff --git a/src/stdlib/atoll.c b/src/stdlib/atoll.c
new file mode 100644 (file)
index 0000000..0e03e0a
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdlib.h>
+#include <ctype.h>
+
+long long atoll(const char *s)
+{
+       long long n=0;
+       int neg=0;
+       while (isspace(*s)) s++;
+       switch (*s) {
+       case '-': neg=1;
+       case '+': s++;
+       }
+       while (isdigit(*s))
+               n = 10*n + *s++ - '0';
+       return neg ? -n : n;
+}
diff --git a/src/stdlib/bsearch.c b/src/stdlib/bsearch.c
new file mode 100644 (file)
index 0000000..61d8936
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+
+void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
+{
+       void *try;
+       int sign;
+       while (nel > 0) {
+               try = (char *)base + width*(nel/2);
+               sign = cmp(key, try);
+               if (!sign) return try;
+               else if (nel == 1) break;
+               else if (sign < 0)
+                       nel /= 2;
+               else {
+                       base = try;
+                       nel -= nel/2;
+               }
+       }
+       return NULL;
+}
diff --git a/src/stdlib/div.c b/src/stdlib/div.c
new file mode 100644 (file)
index 0000000..e42c1f1
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+div_t div(int num, int den)
+{
+       return (div_t){ num/den, num%den };
+}
diff --git a/src/stdlib/frexp.c b/src/stdlib/frexp.c
new file mode 100644 (file)
index 0000000..ae82cb3
--- /dev/null
@@ -0,0 +1,23 @@
+#include <math.h>
+#include <inttypes.h>
+
+double frexp(double x, int *e)
+{
+       union { double d; uint64_t i; } y = { x };
+       int ee = y.i>>52 & 0x7ff;
+
+       if (!ee) {
+               if (x) {
+                       x = frexp(x*0x1p64, e);
+                       *e -= 64;
+               } else *e = 0;
+               return x;
+       } else if (ee == 0x7ff) {
+               return x;
+       }
+
+       *e = ee - 0x3fe;
+       y.i &= 0x800fffffffffffffull;
+       y.i |= 0x3fe0000000000000ull;
+       return y.d;
+}
diff --git a/src/stdlib/frexpf.c b/src/stdlib/frexpf.c
new file mode 100644 (file)
index 0000000..ee5e910
--- /dev/null
@@ -0,0 +1,23 @@
+#include <math.h>
+#include <inttypes.h>
+
+float frexpf(float x, int *e)
+{
+       union { float f; uint32_t i; } y = { x };
+       int ee = y.i>>23 & 0xff;
+
+       if (!ee) {
+               if (x) {
+                       x = frexpf(x*0x1p64, e);
+                       *e -= 64;
+               } else *e = 0;
+               return x;
+       } else if (ee == 0xff) {
+               return x;
+       }
+
+       *e = ee - 0x7e;
+       y.i &= 0x807ffffful;
+       y.i |= 0x3f000000ul;
+       return y.f;
+}
diff --git a/src/stdlib/frexpl.c b/src/stdlib/frexpl.c
new file mode 100644 (file)
index 0000000..ecfff00
--- /dev/null
@@ -0,0 +1,25 @@
+#include <math.h>
+#include <inttypes.h>
+
+/* This version is for 80-bit little endian long double */
+
+long double frexpl(long double x, int *e)
+{
+       union { long double ld; uint16_t hw[5]; } y = { x };
+       int ee = y.hw[4]&0x7fff;
+
+       if (!ee) {
+               if (x) {
+                       x = frexpl(x*0x1p64, e);
+                       *e -= 64;
+               } else *e = 0;
+               return x;
+       } else if (ee == 0x7fff) {
+               return x;
+       }
+
+       *e = ee - 0x3ffe;
+       y.hw[4] &= 0x8000;
+       y.hw[4] |= 0x3ffe;
+       return y.ld;
+}
diff --git a/src/stdlib/imaxabs.c b/src/stdlib/imaxabs.c
new file mode 100644 (file)
index 0000000..8100181
--- /dev/null
@@ -0,0 +1,6 @@
+#include <inttypes.h>
+
+intmax_t imaxabs(intmax_t a)
+{
+       return a>0 ? a : -a;
+}
diff --git a/src/stdlib/imaxdiv.c b/src/stdlib/imaxdiv.c
new file mode 100644 (file)
index 0000000..b2ce821
--- /dev/null
@@ -0,0 +1,6 @@
+#include <inttypes.h>
+
+imaxdiv_t imaxdiv(intmax_t num, intmax_t den)
+{
+       return (imaxdiv_t){ num/den, num%den };
+}
diff --git a/src/stdlib/labs.c b/src/stdlib/labs.c
new file mode 100644 (file)
index 0000000..675b95b
--- /dev/null
@@ -0,0 +1,4 @@
+long labs(long a)
+{
+       return a>0 ? a : -a;
+}
diff --git a/src/stdlib/ldiv.c b/src/stdlib/ldiv.c
new file mode 100644 (file)
index 0000000..36eb960
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+ldiv_t ldiv(long num, long den)
+{
+       return (ldiv_t){ num/den, num%den };
+}
diff --git a/src/stdlib/llabs.c b/src/stdlib/llabs.c
new file mode 100644 (file)
index 0000000..bec4a03
--- /dev/null
@@ -0,0 +1,4 @@
+long long llabs(long long a)
+{
+       return a>0 ? a : -a;
+}
diff --git a/src/stdlib/lldiv.c b/src/stdlib/lldiv.c
new file mode 100644 (file)
index 0000000..7aaf7a0
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+lldiv_t lldiv(long long num, long long den)
+{
+       return (lldiv_t){ num/den, num%den };
+}
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
new file mode 100644 (file)
index 0000000..f5bf3d0
--- /dev/null
@@ -0,0 +1,50 @@
+#include <stdlib.h>
+#include <string.h>
+
+/* A simple heap sort implementation.. only in-place O(nlogn) sort I know. */
+
+#define MIN(a, b) ((a)<(b) ? (a) : (b))
+
+static void swap(char *a, char *b, size_t len)
+{
+       char tmp[256];
+       size_t l;
+       while (len) {
+               l = MIN(sizeof tmp, len);
+               memcpy(tmp, a, l);
+               memcpy(a, b, l);
+               memcpy(b, tmp, l);
+               a += l;
+               b += l;
+               len -= l;
+       }
+}
+
+static void sift(char *base, size_t root, size_t nel, size_t width, int (*cmp)(const void *, const void *))
+{
+       size_t max;
+
+       while (2*root <= nel) {
+               max = 2*root;
+               if (max < nel && cmp(base+max*width, base+(max+1)*width) < 0)
+                       max++;
+               if (cmp(base+root*width, base+max*width) < 0) {
+                       swap(base+root*width, base+max*width, width);
+                       root = max;
+               } else break;
+       }
+}
+
+void qsort(void *_base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
+{
+       char *base = _base;
+       size_t i;
+
+       if (!nel) return;
+       for (i=(nel+1)/2; i; i--)
+               sift(base, i-1, nel-1, width, cmp);
+       for (i=nel-1; i; i--) {
+               swap(base, base+i*width, width);
+               sift(base, 0, i-1, width, cmp);
+       }
+}
diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c
new file mode 100644 (file)
index 0000000..388058f
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+double strtod(const char *s, char **p)
+{
+       return strtold(s, p);
+}
diff --git a/src/stdlib/strtof.c b/src/stdlib/strtof.c
new file mode 100644 (file)
index 0000000..07b32df
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+float strtof(const char *s, char **p)
+{
+       return strtold(s, p);
+}
diff --git a/src/stdlib/strtoimax.c b/src/stdlib/strtoimax.c
new file mode 100644 (file)
index 0000000..1969109
--- /dev/null
@@ -0,0 +1,25 @@
+#include <inttypes.h>
+#include <errno.h>
+#include <ctype.h>
+
+intmax_t strtoimax(const char *s1, char **p, int base)
+{
+       const unsigned char *s = s1;
+       int sign = 0;
+       uintmax_t x;
+
+       /* Initial whitespace */
+       for (; isspace(*s); s++);
+
+       /* Optional sign */
+       if (*s == '-') sign = *s++;
+       else if (*s == '+') s++;
+
+       x = strtoumax(s, p, base);
+       if (x > INTMAX_MAX) {
+               if (!sign || -x != INTMAX_MIN)
+                       errno = ERANGE;
+               return sign ? INTMAX_MIN : INTMAX_MAX;
+       }
+       return sign ? -x : x;
+}
diff --git a/src/stdlib/strtol.c b/src/stdlib/strtol.c
new file mode 100644 (file)
index 0000000..ace820a
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+long strtol(const char *s, char **p, int base)
+{
+       intmax_t x = strtoimax(s, p, base);
+       if (x > LONG_MAX) {
+               errno = ERANGE;
+               return LONG_MAX;
+       } else if (x < LONG_MIN) {
+               errno = ERANGE;
+               return LONG_MIN;
+       }
+       return x;
+}
diff --git a/src/stdlib/strtold.c b/src/stdlib/strtold.c
new file mode 100644 (file)
index 0000000..54f8046
--- /dev/null
@@ -0,0 +1,93 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+
+long double strtold(const char *s1, char **p)
+{
+       const unsigned char *s = s1;
+       long double x = 0;
+       long double frac;
+       int sign = 0;
+       int nonzero = 0;
+       int radix = '.';
+       long e;
+
+       if (!p) p = (char **)&s1;
+
+       /* Initial whitespace */
+       for (; isspace(*s); s++);
+
+       /* Optional sign */
+       if (*s == '-') sign = *s++;
+       else if (*s == '+') s++;
+
+       /* Handle infinities and NaNs. */
+       if ((s[0]|32)=='i' && (s[1]|32)=='n' && (s[2]|32)=='f') {
+               *p = (char *)s + 3;
+               return sign ? -1.0/0.0 : 1.0/0.0;
+       } else if ((s[0]|32)=='n' && (s[1]|32)=='a' && (s[2]|32)=='n') {
+               *p = (char *)s + 3;
+               return 0.0/0.0;
+       }
+
+       /* Possible hex float */
+       if (s[0]=='0' && (s[1]|32)=='x') {
+               /* Mantissa must be non-degenerate */
+               if (!isxdigit(s[2]) && (s[2]!=radix || !isxdigit(s[3]))) {
+                       /* Decimal float 0, 'x' extraneous */
+                       *p = (char *)++s;
+                       return 0;
+               }
+               /* We have a real hex float */
+               s += 2;
+               for (; isxdigit(*s); s++) {
+                       x = 16*x + (isdigit(*s)?*s-'0':(*s|32)-'a');
+                       if (*s!='0') nonzero=1;
+               }
+               if (*s == radix) {
+                       frac = 1.0/16.0;
+                       for (s++; isxdigit(*s); s++) {
+                               x += frac * (isdigit(*s)?*s-'0':(*s|32)-'a');
+                               frac *= 1.0/16.0;
+                               if (*s!='0') nonzero=1;
+                       }
+               }
+               if ((*s|32) == 'p') {
+                       e = strtol(s+1, (void *)&s, 10);
+                       for (; e>0; e--) x *= 2.0;
+                       for (; e<0; e++) x *= 0.5;
+               }
+               if ((nonzero && !x) || !(1.0/x))
+                       errno = ERANGE;
+               *p = (char *)s;
+               return sign ? -x : x;
+       }
+
+       /* Mantissa must be non-degenerate */
+       if (!isdigit(s[0]) && (s[0]!=radix || !isdigit(s[1]))) {
+               *p = (char *)s1;
+               return 0;
+       }
+
+       for (; isdigit(*s); s++) {
+               x = 10*x + *s-'0';
+               if (*s!='0') nonzero=1;
+       }
+       if (*s == radix) {
+               frac = 10.0;
+               for (s++; isdigit(*s); s++) {
+                       x += (*s-'0') / frac;
+                       frac *= 10.0;
+                       if (*s!='0') nonzero=1;
+               }
+       }
+       if ((*s|32)=='e') {
+               e = strtol(++s, (void *)&s, 10);
+               for (; e>0; e--) x *= 10.0;
+               for (; e<0; e++) x /= 10.0;
+       }
+       if ((nonzero && !x) || !(1.0/x))
+               errno = ERANGE;
+       *p = (char*)s;
+       return sign ? -x : x;
+}
diff --git a/src/stdlib/strtoll.c b/src/stdlib/strtoll.c
new file mode 100644 (file)
index 0000000..9ab66fd
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+long long strtoll(const char *s, char **p, int base)
+{
+       intmax_t x = strtoimax(s, p, base);
+       if (x > LLONG_MAX) {
+               errno = ERANGE;
+               return LLONG_MAX;
+       } else if (x < LLONG_MIN) {
+               errno = ERANGE;
+               return LLONG_MIN;
+       }
+       return x;
+}
diff --git a/src/stdlib/strtoul.c b/src/stdlib/strtoul.c
new file mode 100644 (file)
index 0000000..951d5e8
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+unsigned long strtoul(const char *s, char **p, int base)
+{
+       uintmax_t x = strtoumax(s, p, base);
+       if (x > ULONG_MAX) {
+               errno = ERANGE;
+               return ULONG_MAX;
+       }
+       return x;
+}
diff --git a/src/stdlib/strtoull.c b/src/stdlib/strtoull.c
new file mode 100644 (file)
index 0000000..20aa7bd
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+unsigned long long strtoull(const char *s, char **p, int base)
+{
+       uintmax_t x = strtoumax(s, p, base);
+       if (x > ULLONG_MAX) {
+               errno = ERANGE;
+               return ULLONG_MAX;
+       }
+       return x;
+}
diff --git a/src/stdlib/strtoumax.c b/src/stdlib/strtoumax.c
new file mode 100644 (file)
index 0000000..a529f6e
--- /dev/null
@@ -0,0 +1,123 @@
+#include <inttypes.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+
+/* Lookup table for digit values. -1==255>=36 -> invalid */
+static const unsigned char digits[] = {
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
+-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
+-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+};
+
+uintmax_t strtoumax(const char *s1, char **p, int base)
+{
+       const unsigned char *s = s1;
+       size_t x1, z1;
+       uintmax_t x, z=0;
+       int sign = 0;
+       int shift;
+
+       if (!p) p = (char **)&s1;
+
+       /* Initial whitespace */
+       for (; isspace(*s); s++);
+
+       /* Optional sign */
+       if (*s == '-') sign = *s++;
+       else if (*s == '+') s++;
+
+       /* Default base 8, 10, or 16 depending on prefix */
+       if (base == 0) {
+               if (s[0] == '0') {
+                       if ((s[1]|32) == 'x') base = 16;
+                       else base = 8;
+               } else {
+                       base = 10;
+               }
+       }
+
+       if ((unsigned)base-2 > 36-2 || digits[*s]>=base) {
+               *p = (char *)s1;
+               errno = EINVAL;
+               return 0;
+       }
+
+       /* Main loops. Only use big types if we have to. */
+       if (base == 10) {
+               for (x1=0; isdigit(*s) && x1<=SIZE_MAX/10-10; s++)
+                       x1 = 10*x1 + *s-'0';
+               for (x=x1; isdigit(*s) && x<=UINTMAX_MAX/10-10; s++)
+                       x = 10*x + *s-'0';
+               if (isdigit(*s)) {
+                       if (isdigit(s[1]) || 10*x>UINTMAX_MAX-(*s-'0'))
+                               goto overflow;
+                       x = 10*x + *s-'0';
+               }
+       } else if (!(base & base/2)) {
+               if (base == 16) {
+                       if (s[0]=='0' && (s[1]|32)=='x' && digits[s[2]]<16)
+                               s+=2;
+                       shift=4;
+                       z1 = SIZE_MAX/16;
+                       z = UINTMAX_MAX/16;
+               } else if (base == 8) {
+                       shift=3;
+                       z1 = SIZE_MAX/8;
+                       z = UINTMAX_MAX/8;
+               } else if (base == 2) {
+                       shift=1;
+                       z1 = SIZE_MAX/2;
+                       z = UINTMAX_MAX/2;
+               } else if (base == 4) {
+                       shift=2;
+                       z1 = SIZE_MAX/4;
+                       z = UINTMAX_MAX/4;
+               } else /* if (base == 32) */ {
+                       shift=5;
+                       z1 = SIZE_MAX/32;
+                       z = UINTMAX_MAX/32;
+               }
+               for (x1=0; digits[*s]<base && x1<=z1; s++)
+                       x1 = (x1<<shift) + digits[*s];
+               for (x=x1; digits[*s]<base && x<=z; s++)
+                       x = (x<<shift) + digits[*s];
+               if (digits[*s] < base) goto overflow;
+       } else {
+               z1 = SIZE_MAX/base-base;
+               for (x1=0; digits[*s]<base && x1<=z1; s++)
+                       x1 = x1*base + digits[*s];
+               if (digits[*s]<base)
+                       z = UINTMAX_MAX/base-base;
+               for (x=x1; digits[*s]<base && x<=z; s++)
+                       x = x*base + digits[*s];
+               if (digits[*s] < base) {
+                       if (digits[s[1]]<base || x*base>UINTMAX_MAX-digits[*s])
+                               goto overflow;
+                       x = x*base + digits[*s];
+               }
+       }
+
+       *p = (char *)s;
+       return sign ? -x : x;
+
+overflow:
+       for (; digits[*s] < base; s++);
+       *p = (char *)s;
+       errno = ERANGE;
+       return UINTMAX_MAX;
+}
diff --git a/src/stdlib/wcstoimax.c b/src/stdlib/wcstoimax.c
new file mode 100644 (file)
index 0000000..861fcb5
--- /dev/null
@@ -0,0 +1,24 @@
+#include <wchar.h>
+#include <inttypes.h>
+#include <errno.h>
+
+intmax_t wcstoimax(const wchar_t *s, wchar_t **p, int base)
+{
+       int sign = 0;
+       uintmax_t x;
+
+       /* Initial whitespace */
+       for (; iswspace(*s); s++);
+
+       /* Optional sign */
+       if (*s == '-') sign = *s++;
+       else if (*s == '+') s++;
+
+       x = wcstoumax(s, p, base);
+       if (x > INTMAX_MAX) {
+               if (!sign || -x != INTMAX_MIN)
+                       errno = ERANGE;
+               return sign ? INTMAX_MIN : INTMAX_MAX;
+       }
+       return sign ? -x : x;
+}
diff --git a/src/stdlib/wcstol.c b/src/stdlib/wcstol.c
new file mode 100644 (file)
index 0000000..aad62e5
--- /dev/null
@@ -0,0 +1,18 @@
+#include <wchar.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+long wcstol(const wchar_t *s, wchar_t **p, int base)
+{
+       intmax_t x = wcstoimax(s, p, base);
+       if (x > LONG_MAX) {
+               errno = ERANGE;
+               return LONG_MAX;
+       } else if (x < LONG_MIN) {
+               errno = ERANGE;
+               return LONG_MIN;
+       }
+       return x;
+}
diff --git a/src/stdlib/wcstoll.c b/src/stdlib/wcstoll.c
new file mode 100644 (file)
index 0000000..ddfea74
--- /dev/null
@@ -0,0 +1,18 @@
+#include <wchar.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+long long wcstoll(const wchar_t *s, wchar_t **p, int base)
+{
+       intmax_t x = wcstoimax(s, p, base);
+       if (x > LLONG_MAX) {
+               errno = ERANGE;
+               return LLONG_MAX;
+       } else if (x < LLONG_MIN) {
+               errno = ERANGE;
+               return LLONG_MIN;
+       }
+       return x;
+}
diff --git a/src/stdlib/wcstoul.c b/src/stdlib/wcstoul.c
new file mode 100644 (file)
index 0000000..e39faaf
--- /dev/null
@@ -0,0 +1,15 @@
+#include <wchar.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+unsigned long wcstoul(const wchar_t *s, wchar_t **p, int base)
+{
+       uintmax_t x = wcstoumax(s, p, base);
+       if (x > ULONG_MAX) {
+               errno = ERANGE;
+               return ULONG_MAX;
+       }
+       return x;
+}
diff --git a/src/stdlib/wcstoull.c b/src/stdlib/wcstoull.c
new file mode 100644 (file)
index 0000000..e324dfb
--- /dev/null
@@ -0,0 +1,15 @@
+#include <wchar.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+
+unsigned long long wcstoull(const wchar_t *s, wchar_t **p, int base)
+{
+       uintmax_t x = wcstoumax(s, p, base);
+       if (x > ULLONG_MAX) {
+               errno = ERANGE;
+               return ULLONG_MAX;
+       }
+       return x;
+}
diff --git a/src/stdlib/wcstoumax.c b/src/stdlib/wcstoumax.c
new file mode 100644 (file)
index 0000000..a8f4680
--- /dev/null
@@ -0,0 +1,47 @@
+#include <wchar.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+
+uintmax_t wcstoumax(const wchar_t *s, wchar_t **p, int base)
+{
+       /* Large enough for largest value in binary */
+       char buf[sizeof(uintmax_t)*8+2];
+       int sign = 0, skipped=0;
+
+       if (!p) p = (wchar_t **)&s;
+
+       if (base && (unsigned)base-2 > 36-2) {
+               *p = (wchar_t *)s;
+               errno = EINVAL;
+               return 0;
+       }
+
+       /* Initial whitespace */
+       for (; iswspace(*s); s++);
+
+       /* Optional sign */
+       if (*s == '-') sign = *s++;
+       else if (*s == '+') s++;
+
+       /* Skip leading zeros but don't allow leading zeros before "0x". */
+       for (; s[0]=='0' && s[1]=='0'; s++) skipped=1;
+       if (skipped && (base==0 || base==16) && (s[1]|32)=='x') {
+               *p = (wchar_t *)(s+1);
+               return 0;
+       }
+
+       /* Convert to normal char string so we can use strtoumax */
+       buf[0] = sign;
+       if (wcstombs(buf+!!sign, s, sizeof buf-1) < 0) return 0;
+       buf[sizeof buf-1]=0;
+
+       /* Compute final position */
+       if (p) {
+               if ((base==0 || base==16) && s[0]=='0' && (s[1]|32)=='x' && iswxdigit(s[2])) s+=2;
+               for(;*s&&((unsigned)*s-'0'<base||((unsigned)*s|32)-'a'<base-10);s++);
+               *p = (wchar_t *)s;
+       }
+
+       return strtoumax(buf, 0, base);
+}
diff --git a/src/string/bcmp.c b/src/string/bcmp.c
new file mode 100644 (file)
index 0000000..5d6a388
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+#include <strings.h>
+
+int bcmp(const void *s1, const void *s2, size_t n)
+{
+       return memcmp(s1, s2, n);
+}
diff --git a/src/string/bcopy.c b/src/string/bcopy.c
new file mode 100644 (file)
index 0000000..e76272f
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+#include <strings.h>
+
+void bcopy(const void *s1, void *s2, size_t n)
+{
+       memmove(s2, s1, n);
+}
diff --git a/src/string/bzero.c b/src/string/bzero.c
new file mode 100644 (file)
index 0000000..0f98b4a
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+#include <strings.h>
+
+void bzero(void *s, size_t n)
+{
+       memset(s, 0, n);
+}
diff --git a/src/string/index.c b/src/string/index.c
new file mode 100644 (file)
index 0000000..dd61125
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+#include <strings.h>
+
+char *index(const char *s, int c)
+{
+       return strchr(s, c);
+}
diff --git a/src/string/memchr.c b/src/string/memchr.c
new file mode 100644 (file)
index 0000000..a0472f7
--- /dev/null
@@ -0,0 +1,24 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+void *memchr(const void *src, int c, size_t n)
+{
+       const unsigned char *s = src;
+       c = (unsigned char)c;
+       for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
+       if (n && *s != c) {
+               const size_t *w;
+               size_t k = ONES * c;
+               for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
+               for (s = (const void *)w; n && *s != c; s++, n--);
+       }
+       return n ? (void *)s : 0;
+}
diff --git a/src/string/memcmp.c b/src/string/memcmp.c
new file mode 100644 (file)
index 0000000..bdbce9f
--- /dev/null
@@ -0,0 +1,8 @@
+#include <string.h>
+
+int memcmp(const void *vl, const void *vr, size_t n)
+{
+       const unsigned char *l=vl, *r=vr;
+       for (; n && *l == *r; n--, l++, r++);
+       return n ? *l-*r : 0;
+}
diff --git a/src/string/memcpy.c b/src/string/memcpy.c
new file mode 100644 (file)
index 0000000..02cb469
--- /dev/null
@@ -0,0 +1,29 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+       unsigned char *d = dest;
+       const unsigned char *s = src;
+
+       if (((uintptr_t)d & ALIGN) != ((uintptr_t)s & ALIGN))
+               goto misaligned;
+
+       for (; ((uintptr_t)d & ALIGN) && n; n--) *d++ = *s++;
+       if (n) {
+               size_t *wd = (void *)d;
+               const size_t *ws = (const void *)s;
+
+               for (; n>=SS; n-=SS) *wd++ = *ws++;
+               d = (void *)wd;
+               s = (const void *)ws;
+misaligned:
+               for (; n; n--) *d++ = *s++;
+       }
+       return dest;
+}
diff --git a/src/string/memmove.c b/src/string/memmove.c
new file mode 100644 (file)
index 0000000..22bb4b3
--- /dev/null
@@ -0,0 +1,14 @@
+#include <string.h>
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+       char *d = dest;
+       const char *s = src;
+       if (d==s) return d;
+       if ((size_t)(d-s) < n) {
+               while (n--) d[n] = s[n];
+               return dest;
+       }
+       /* Assumes memcpy is overlap-safe when dest < src */
+       return memcpy(d, s, n);
+}
diff --git a/src/string/mempcpy.c b/src/string/mempcpy.c
new file mode 100644 (file)
index 0000000..e54251c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+void *mempcpy(void *dest, void *src, size_t n)
+{
+       memcpy(dest, src, n);
+       return (char *)dest + n;
+}
diff --git a/src/string/memset.c b/src/string/memset.c
new file mode 100644 (file)
index 0000000..20e47c4
--- /dev/null
@@ -0,0 +1,21 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+
+void *memset(void *dest, int c, size_t n)
+{
+       unsigned char *s = dest;
+       c = (unsigned char)c;
+       for (; ((uintptr_t)s & ALIGN) && n; n--) *s++ = c;
+       if (n) {
+               size_t *w, k = ONES * c;
+               for (w = (void *)s; n>=SS; n-=SS, w++) *w = k;
+               for (s = (void *)w; n; n--, s++) *s = c;
+       }
+       return dest;
+}
diff --git a/src/string/rindex.c b/src/string/rindex.c
new file mode 100644 (file)
index 0000000..17df2bf
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+#include <strings.h>
+
+char *rindex(const char *s, int c)
+{
+       return strrchr(s, c);
+}
diff --git a/src/string/stpcpy.c b/src/string/stpcpy.c
new file mode 100644 (file)
index 0000000..10ca493
--- /dev/null
@@ -0,0 +1,29 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include "libc.h"
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__stpcpy(char *d, const char *s)
+{
+       size_t *wd;
+       const size_t *ws;
+
+       if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
+               for (; (*d=*s) && ((uintptr_t)s & ALIGN); s++, d++);
+               if (!*s) return d;
+               wd=(void *)d; ws=(const void *)s;
+               for (; !HASZERO(*ws); *wd++ = *ws++);
+               d=(void *)wd; s=(const void *)ws;
+       }
+       for (; (*d=*s); s++, d++);
+
+       return d;
+}
+
+weak_alias(__stpcpy, stpcpy);
diff --git a/src/string/stpncpy.c b/src/string/stpncpy.c
new file mode 100644 (file)
index 0000000..a877f5f
--- /dev/null
@@ -0,0 +1,32 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include "libc.h"
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__stpncpy(char *d, const char *s, size_t n)
+{
+       size_t *wd;
+       const size_t *ws;
+
+       if (((uintptr_t)s & ALIGN) != ((uintptr_t)d & ALIGN)) {
+               for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
+               if (!n || !*s) goto tail;
+               wd=(void *)d; ws=(const void *)s;
+               for (; n>=sizeof(size_t) && !HASZERO(*ws);
+                      n-=sizeof(size_t), ws++, *wd++) *wd = *ws;
+               d=(void *)wd; s=(const void *)ws;
+       }
+       for (; n && (*d=*s); n--, s++, d++);
+tail:
+       memset(d, 0, n);
+       return d;
+}
+
+weak_alias(__stpncpy, stpncpy);
+
diff --git a/src/string/strcasecmp.c b/src/string/strcasecmp.c
new file mode 100644 (file)
index 0000000..dd87905
--- /dev/null
@@ -0,0 +1,9 @@
+#include <strings.h>
+#include <ctype.h>
+
+int strcasecmp(const char *_l, const char *_r)
+{
+       const unsigned char *l=_l, *r=_r;
+       for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++);
+       return tolower(*l) - tolower(*r);
+}
diff --git a/src/string/strcasestr.c b/src/string/strcasestr.c
new file mode 100644 (file)
index 0000000..f1cb0e8
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strcasestr(const char *h, const char *n)
+{
+       //FIXME!
+       return strstr(h, n);
+}
diff --git a/src/string/strcat.c b/src/string/strcat.c
new file mode 100644 (file)
index 0000000..29fdb61
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strcat(char *dest, const char *src)
+{
+       strcpy(dest + strlen(dest), src);
+       return dest;
+}
diff --git a/src/string/strchr.c b/src/string/strchr.c
new file mode 100644 (file)
index 0000000..e606f4f
--- /dev/null
@@ -0,0 +1,23 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *strchr(const char *s, int c)
+{
+       c = (char)c;
+       if (!c) return (char *)s + strlen(s);
+       for (; ((uintptr_t)s & ALIGN) && *s && *s != c; s++);
+       if (*s && *s != c) {
+               const size_t *w;
+               size_t k = ONES * c;
+               for (w = (const void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
+               for (s = (const void *)w; *s && *s != c; s++);
+       }
+       return *s ? (char *)s : 0;
+}
diff --git a/src/string/strchrnul.c b/src/string/strchrnul.c
new file mode 100644 (file)
index 0000000..5e0c1a1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strchrnul(const char *s, int c)
+{
+       char *p = strchr(s, c);
+       return p ? p : (char *)s + strlen(s);
+}
diff --git a/src/string/strcmp.c b/src/string/strcmp.c
new file mode 100644 (file)
index 0000000..91eb740
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+int strcmp(const char *l, const char *r)
+{
+       for (; *l==*r && *l && *r; l++, r++);
+       return *(unsigned char *)l - *(unsigned char *)r;
+}
diff --git a/src/string/strcpy.c b/src/string/strcpy.c
new file mode 100644 (file)
index 0000000..7675e9c
--- /dev/null
@@ -0,0 +1,16 @@
+#include <string.h>
+
+char *__stpcpy(char *, const char *);
+
+char *strcpy(char *dest, const char *src)
+{
+#if 1
+       __stpcpy(dest, src);
+       return dest;
+#else
+       const unsigned char *s = src;
+       unsigned char *d = dest;
+       while ((*d++ = *s++));
+       return dest;
+#endif
+}
diff --git a/src/string/strcspn.c b/src/string/strcspn.c
new file mode 100644 (file)
index 0000000..439b7be
--- /dev/null
@@ -0,0 +1,20 @@
+#include <string.h>
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+size_t strcspn(const char *_s, const char *_c)
+{
+       const unsigned char *s = _s;
+       const unsigned char *c = _c;
+       const unsigned char *a = s;
+       size_t byteset[32/sizeof(size_t)];
+
+       if (!c[0]) return strlen(s);
+       if (!c[1]) return (s=strchr(s, *c)) ? s-a : strlen(a);
+
+       memset(byteset, 0, sizeof byteset);
+       for (; *c && BITOP(byteset, *c, |=); c++);
+       for (; *s && !BITOP(byteset, *s, &); s++);
+       return s-a;
+}
diff --git a/src/string/strdup.c b/src/string/strdup.c
new file mode 100644 (file)
index 0000000..dd5f80c
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include <string.h>
+#include "libc.h"
+
+char *__strdup(const char *s)
+{
+       size_t l = strlen(s);
+       char *d = malloc(l+1);
+       if (!d) return NULL;
+       return memcpy(d, s, l+1);
+}
+
+weak_alias(__strdup, strdup);
diff --git a/src/string/strerror_r.c b/src/string/strerror_r.c
new file mode 100644 (file)
index 0000000..6fdd4ce
--- /dev/null
@@ -0,0 +1,11 @@
+#include <string.h>
+#include <errno.h>
+
+int strerror_r(int err, char *buf, size_t buflen)
+{
+       char *msg = strerror(err);
+       if (strlen(msg) >= buflen)
+               return ERANGE;
+       strcpy(buf, msg);
+       return 0;
+}
diff --git a/src/string/strlcat.c b/src/string/strlcat.c
new file mode 100644 (file)
index 0000000..a6b94c4
--- /dev/null
@@ -0,0 +1,8 @@
+#include <string.h>
+
+size_t strlcat(char *d, const char *s, size_t n)
+{
+       size_t l = strnlen(d, n);
+       if (l == n) return l + strlen(s);
+       return l + strlcpy(d+l, s, n-l);
+}
diff --git a/src/string/strlcpy.c b/src/string/strlcpy.c
new file mode 100644 (file)
index 0000000..bbebf1d
--- /dev/null
@@ -0,0 +1,32 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include "libc.h"
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+size_t strlcpy(char *d, const char *s, size_t n)
+{
+       char *d0 = d;
+       size_t *wd;
+       const size_t *ws;
+
+       if (!n--) goto finish;
+       if (((uintptr_t)s & ALIGN) != ((uintptr_t)d & ALIGN)) {
+               for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
+               if (n && *s) {
+                       wd=(void *)d; ws=(const void *)s;
+                       for (; n>=sizeof(size_t) && !HASZERO(*ws);
+                              n-=sizeof(size_t), ws++, *wd++) *wd = *ws;
+                       d=(void *)wd; s=(const void *)ws;
+               }
+       }
+       for (; n && (*d=*s); n--, s++, d++);
+       *d = 0;
+finish:
+       return d-d0 + strlen(s);
+}
diff --git a/src/string/strlen.c b/src/string/strlen.c
new file mode 100644 (file)
index 0000000..936fb5c
--- /dev/null
@@ -0,0 +1,21 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+size_t strlen(const char *s)
+{
+       const char *a = s;
+       const size_t *w;
+       for (; ((uintptr_t)s & ALIGN) && *s; s++);
+       if (*s) {
+               for (w = (const void *)s; !HASZERO(*w); w++);
+               for (s = (const void *)w; *s; s++);
+       }
+       return s-a;
+}
diff --git a/src/string/strncasecmp.c b/src/string/strncasecmp.c
new file mode 100644 (file)
index 0000000..4f9230e
--- /dev/null
@@ -0,0 +1,10 @@
+#include <strings.h>
+#include <ctype.h>
+
+int strncasecmp(const char *_l, const char *_r, size_t n)
+{
+       const unsigned char *l=_l, *r=_r;
+       if (!n--) return 0;
+       for (; *l && *r && n && (*l == *r || tolower(*l) == tolower(*r)); l++, r++, n--);
+       return tolower(*l) - tolower(*r);
+}
diff --git a/src/string/strncat.c b/src/string/strncat.c
new file mode 100644 (file)
index 0000000..255b7a7
--- /dev/null
@@ -0,0 +1,10 @@
+#include <string.h>
+
+char *strncat(char *d, const char *s, size_t n)
+{
+       char *a = d;
+       d += strlen(d);
+       while (n && (*d++ = *s++)) n--;
+       *d++ = 0;
+       return a;
+}
diff --git a/src/string/strncmp.c b/src/string/strncmp.c
new file mode 100644 (file)
index 0000000..52ba032
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+
+int strncmp(const char *_l, const char *_r, size_t n)
+{
+       const unsigned char *l=_l, *r=_r;
+       if (!n--) return 0;
+       for (; *l && *r && n && *l == *r ; l++, r++, n--);
+       return *l - *r;
+}
diff --git a/src/string/strncpy.c b/src/string/strncpy.c
new file mode 100644 (file)
index 0000000..c0cd797
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+
+char *__stpncpy(char *, const char *, size_t);
+
+char *strncpy(char *d, const char *s, size_t n)
+{
+       __stpncpy(d, s, n);
+       return d;
+}
diff --git a/src/string/strndup.c b/src/string/strndup.c
new file mode 100644 (file)
index 0000000..617d27b
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include <string.h>
+
+char *strndup(const char *s, size_t n)
+{
+       size_t l = strnlen(s, n);
+       char *d = malloc(l+1);
+       if (!d) return NULL;
+       memcpy(d, s, l);
+       d[l] = 0;
+       return d;
+}
diff --git a/src/string/strnlen.c b/src/string/strnlen.c
new file mode 100644 (file)
index 0000000..6442eb7
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+size_t strnlen(const char *s, size_t n)
+{
+       const char *p = memchr(s, 0, n);
+       return p ? p-s : n;
+}
diff --git a/src/string/strpbrk.c b/src/string/strpbrk.c
new file mode 100644 (file)
index 0000000..55947c6
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strpbrk(const char *s, const char *b)
+{
+       s += strcspn(s, b);
+       return *s ? (char *)s : 0;
+}
diff --git a/src/string/strrchr.c b/src/string/strrchr.c
new file mode 100644 (file)
index 0000000..31c8e0b
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+
+char *strrchr(const char *s, int c)
+{
+       const char *p;
+       c = (char)c;
+       for (p=s+strlen(s); p>=s && *p!=c; p--);
+       return p>=s ? (char *)p : 0;
+}
diff --git a/src/string/strsep.c b/src/string/strsep.c
new file mode 100644 (file)
index 0000000..1bfe1db
--- /dev/null
@@ -0,0 +1,12 @@
+#include <string.h>
+
+char *strsep(char **str, const char *sep)
+{
+       char *s = *str, *end;
+       if (!s) return NULL;
+       end = s + strcspn(s, sep);
+       if (*end) *end++ = 0;
+       else end = 0;
+       *str = end;
+       return s;
+}
diff --git a/src/string/strsignal.c b/src/string/strsignal.c
new file mode 100644 (file)
index 0000000..72fba8d
--- /dev/null
@@ -0,0 +1,98 @@
+#include <signal.h>
+
+#if (SIGHUP == 1) && (SIGINT == 2) && (SIGQUIT == 3) && (SIGILL == 4) \
+ && (SIGTRAP == 5) && (SIGABRT == 6) && (SIGBUS == 7) && (SIGFPE == 8) \
+ && (SIGKILL == 9) && (SIGUSR1 == 10) && (SIGSEGV == 11) && (SIGUSR2 == 12) \
+ && (SIGPIPE == 13) && (SIGALRM == 14) && (SIGTERM == 15) && (SIGSTKFLT == 16) \
+ && (SIGCHLD == 17) && (SIGCONT == 18) && (SIGSTOP == 19) && (SIGTSTP == 20) \
+ && (SIGTTIN == 21) && (SIGTTOU == 22) && (SIGURG == 23) && (SIGXCPU == 24) \
+ && (SIGXFSZ == 25) && (SIGVTALRM == 26) && (SIGPROF == 27) && (SIGWINCH == 28) \
+ && (SIGPOLL == 29) && (SIGPWR == 30) && (SIGSYS == 31)
+
+#define sigmap(x) x
+
+#else
+
+static const char map[] = {
+       [SIGHUP]    = 1,
+       [SIGINT]    = 2,
+       [SIGQUIT]   = 3,
+       [SIGILL]    = 4,
+       [SIGTRAP]   = 5,
+       [SIGABRT]   = 6,
+       [SIGBUS]    = 7,
+       [SIGFPE]    = 8,
+       [SIGKILL]   = 9,
+       [SIGUSR1]   = 10,
+       [SIGSEGV]   = 11,
+       [SIGUSR2]   = 12,
+       [SIGPIPE]   = 13,
+       [SIGALRM]   = 14,
+       [SIGTERM]   = 15,
+       [SIGSTKFLT] = 16,
+       [SIGCHLD]   = 17,
+       [SIGCONT]   = 18,
+       [SIGSTOP]   = 19,
+       [SIGTSTP]   = 20,
+       [SIGTTIN]   = 21,
+       [SIGTTOU]   = 22,
+       [SIGURG]    = 23,
+       [SIGXCPU]   = 24,
+       [SIGXFSZ]   = 25,
+       [SIGVTALRM] = 26,
+       [SIGPROF]   = 27,
+       [SIGWINCH]  = 28,
+       [SIGPOLL]   = 29,
+       [SIGPWR]    = 30,
+       [SIGSYS]    = 31
+};
+
+#define sigmap(x) ((unsigned)(x) > sizeof map ? 0 : map[(unsigned)(x)])
+
+#endif
+
+static const char strings[] =
+       "Unknown signal\0"
+       "Hangup\0"
+       "Interrupt\0"
+       "Quit\0"
+       "Illegal instruction\0"
+       "Trace/breakpoint trap\0"
+       "Aborted\0"
+       "Bus error\0"
+       "Floating point exception\0"
+       "Killed\0"
+       "User defined signal 1\0"
+       "Segmentation fault\0"
+       "User defined signal 2\0"
+       "Broken pipe\0"
+       "Alarm clock\0"
+       "Terminated\0"
+       "Stack fault\0"
+       "Child exited\0"
+       "Continued\0"
+       "Stopped (signal)\0"
+       "Stopped\0"
+       "Stopped (tty input)\0"
+       "Stopped (tty output)\0"
+       "Urgent I/O condition\0"
+       "CPU time limit exceeded\0"
+       "File size limit exceeded\0"
+       "Virtual timer expired\0"
+       "Profiling timer expired\0"
+       "Window changed\0"
+       "I/O possible\0"
+       "Power failure\0"
+       "Bad system call";
+
+char *strsignal(int signum)
+{
+       char *s = (char *)strings;
+
+       signum = sigmap(signum);
+       if ((unsigned)signum - 1 > 31) signum = 0;
+
+       for (; signum--; s++) for (; *s; s++);
+
+       return s;
+}
diff --git a/src/string/strspn.c b/src/string/strspn.c
new file mode 100644 (file)
index 0000000..59b063e
--- /dev/null
@@ -0,0 +1,22 @@
+#include <string.h>
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+size_t strspn(const char *_s, const char *_c)
+{
+       const unsigned char *s = _s;
+       const unsigned char *c = _c;
+       const unsigned char *a = s;
+       size_t byteset[32/sizeof(size_t)] = { 0 };
+
+       if (!c[0]) return 0;
+       if (!c[1]) {
+               for (; *s == *c; s++);
+               return s-a;
+       }
+
+       for (; *c && BITOP(byteset, *c, |=); c++);
+       for (; *s && BITOP(byteset, *s, &); s++);
+       return s-a;
+}
diff --git a/src/string/strstr.c b/src/string/strstr.c
new file mode 100644 (file)
index 0000000..4d536a7
--- /dev/null
@@ -0,0 +1,166 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+       uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+       for (h++; *h && hw != nw; hw = hw<<8 | *++h);
+       return *h ? (char *)h-1 : 0;
+}
+
+static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+       uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
+       uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
+       for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
+       return *h ? (char *)h-2 : 0;
+}
+
+static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+       uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+       uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+       for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
+       return *h ? (char *)h-3 : 0;
+}
+
+#if 0
+static char *naive_strstr(const char *h, const char *n)
+{
+       size_t i;
+       for (i=0; n[i] && h[i]; i++)
+       for (   ; n[i] != h[i]; h++, i=0);
+       return n[i] ? 0 : (char *)h;
+}
+#endif
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
+{
+       const unsigned char *z;
+       size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+       size_t byteset[32 / sizeof(size_t)] = { 0 };
+       size_t shift[256];
+
+       /* Computing length of needle and fill shift table */
+       for (l=0; n[l] && h[l]; l++)
+               BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
+       if (n[l]) return 0; /* hit the end of h */
+
+       /* Compute maximal suffix */
+       ip = -1; jp = 0; k = p = 1;
+       while (jp+k<l) {
+               if (n[ip+k] == n[jp+k]) {
+                       if (k == p) {
+                               jp += p;
+                               k = 1;
+                       } else k++;
+               } else if (n[ip+k] > n[jp+k]) {
+                       jp += k;
+                       k = 1;
+                       p = jp - ip;
+               } else {
+                       ip = jp++;
+                       k = p = 1;
+               }
+       }
+       ms = ip;
+       p0 = p;
+
+       /* And with the opposite comparison */
+       ip = -1; jp = 0; k = p = 1;
+       while (jp+k<l) {
+               if (n[ip+k] == n[jp+k]) {
+                       if (k == p) {
+                               jp += p;
+                               k = 1;
+                       } else k++;
+               } else if (n[ip+k] < n[jp+k]) {
+                       jp += k;
+                       k = 1;
+                       p = jp - ip;
+               } else {
+                       ip = jp++;
+                       k = p = 1;
+               }
+       }
+       if (ip+1 > ms+1) ms = ip;
+       else p = p0;
+
+       /* Periodic needle? */
+       if (memcmp(n, n+p, ms+1)) {
+               mem0 = 0;
+               p = MAX(ms, l-ms-1) + 1;
+       } else mem0 = l-p;
+       mem = 0;
+
+       /* Initialize incremental end-of-haystack pointer */
+       z = h;
+
+       /* Search loop */
+       for (;;) {
+               /* Update incremental end-of-haystack pointer */
+               if (z-h < l) {
+                       /* Fast estimate for MIN(l,63) */
+                       size_t grow = l | 63;
+                       const char *z2 = memchr(z, 0, grow);
+                       if (z2) {
+                               z = z2;
+                               if (z-h < l) return 0;
+                       } else z += grow;
+               }
+
+               /* Check last byte first; advance by shift on mismatch */
+               if (BITOP(byteset, h[l-1], &)) {
+                       k = l-shift[h[l-1]];
+                       //printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l);
+                       if (k) {
+                               if (mem0 && mem && k < p) k = l-p;
+                               h += k;
+                               mem = 0;
+                               continue;
+                       }
+               } else {
+                       h += l;
+                       mem = 0;
+                       continue;
+               }
+
+               /* Compare right half */
+               for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+               if (n[k]) {
+                       h += k-ms;
+                       mem = 0;
+                       continue;
+               }
+               /* Compare left half */
+               for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+               if (k == mem) return (char *)h;
+               h += p;
+               mem = mem0;
+       }
+}
+
+char *strstr(const char *h, const char *n)
+{
+       /* Return immediately on empty needle */
+       if (!n[0]) return (char *)h;
+
+       /* Use faster algorithms for short needles */
+       h = strchr(h, *n);
+       if (!h || !n[1]) return (char *)h;
+       if (!h[1]) return 0;
+       if (!n[2]) return twobyte_strstr(h, n);
+       if (!h[2]) return 0;
+       if (!n[3]) return threebyte_strstr(h, n);
+       if (!h[3]) return 0;
+       if (!n[4]) return fourbyte_strstr(h, n);
+
+       return twoway_strstr(h, n);
+}
diff --git a/src/string/strtok.c b/src/string/strtok.c
new file mode 100644 (file)
index 0000000..1ba221c
--- /dev/null
@@ -0,0 +1,13 @@
+#include <string.h>
+
+char *strtok(char *s, const char *sep)
+{
+       static char *p;
+       if (!s && !(s = p)) return NULL;
+       s += strspn(s, sep);
+       if (!*s) return p = 0;
+       p = s + strcspn(s, sep);
+       if (*p) *p++ = 0;
+       else p = 0;
+       return s;
+}
diff --git a/src/string/strtok_r.c b/src/string/strtok_r.c
new file mode 100644 (file)
index 0000000..c763897
--- /dev/null
@@ -0,0 +1,12 @@
+#include <string.h>
+
+char *strtok_r(char *s, const char *sep, char **p)
+{
+       if (!s && !(s = *p)) return NULL;
+       s += strspn(s, sep);
+       if (!*s) return *p = 0;
+       *p = s + strcspn(s, sep);
+       if (**p) *(*p)++ = 0;
+       else *p = 0;
+       return s;
+}
diff --git a/src/string/swab.c b/src/string/swab.c
new file mode 100644 (file)
index 0000000..b213288
--- /dev/null
@@ -0,0 +1,13 @@
+#include <unistd.h>
+
+void swab(const void *_src, void *_dest, ssize_t n)
+{
+       const char *src = _src;
+       char *dest = _dest;
+       for (; n>0; n-=2) {
+               dest[0] = src[1];
+               dest[1] = src[0];
+               dest += 2;
+               src += 2;
+       }
+}
diff --git a/src/string/wcscat.c b/src/string/wcscat.c
new file mode 100644 (file)
index 0000000..946f16e
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+wchar_t *wcscat(wchar_t *dest, const wchar_t *src)
+{
+       wcscpy(dest + wcslen(dest), src);
+       return dest;
+}
diff --git a/src/string/wcschr.c b/src/string/wcschr.c
new file mode 100644 (file)
index 0000000..8dfc2f3
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wcschr(const wchar_t *s, wchar_t c)
+{
+       if (!c) return (wchar_t *)s + wcslen(s);
+       for (; *s && *s != c; s++);
+       return *s ? (wchar_t *)s : 0;
+}
diff --git a/src/string/wcscmp.c b/src/string/wcscmp.c
new file mode 100644 (file)
index 0000000..26eeee7
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+int wcscmp(const wchar_t *l, const wchar_t *r)
+{
+       for (; *l==*r && *l && *r; l++, r++);
+       return *l - *r;
+}
diff --git a/src/string/wcscpy.c b/src/string/wcscpy.c
new file mode 100644 (file)
index 0000000..e0ac194
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wcscpy(wchar_t *d, const wchar_t *s)
+{
+       wchar_t *a = d;
+       while ((*d++ = *s++));
+       return a;
+}
diff --git a/src/string/wcscspn.c b/src/string/wcscspn.c
new file mode 100644 (file)
index 0000000..c4e5272
--- /dev/null
@@ -0,0 +1,10 @@
+#include <wchar.h>
+
+size_t wcscspn(const wchar_t *s, const wchar_t *c)
+{
+       const wchar_t *a;
+       if (!c[0]) return wcslen(s);
+       if (!c[1]) return (s=wcschr(a=s, *c)) ? s-a : wcslen(a);
+       for (a=s; *s && !wcschr(c, *s); s++);
+       return s-a;
+}
diff --git a/src/string/wcslen.c b/src/string/wcslen.c
new file mode 100644 (file)
index 0000000..1b7b665
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+size_t wcslen(const wchar_t *s)
+{
+       const wchar_t *a;
+       for (a=s; *s; s++);
+       return s-a;
+}
diff --git a/src/string/wcsncat.c b/src/string/wcsncat.c
new file mode 100644 (file)
index 0000000..b07abe4
--- /dev/null
@@ -0,0 +1,10 @@
+#include <wchar.h>
+
+wchar_t *wcsncat(wchar_t *d, const wchar_t *s, size_t n)
+{
+       wchar_t *a = d;
+       d += wcslen(d);
+       while (n && (*d++ = *s++)) n--;
+       *d++ = 0;
+       return a;
+}
diff --git a/src/string/wcsncmp.c b/src/string/wcsncmp.c
new file mode 100644 (file)
index 0000000..1b159f4
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n)
+{
+       for (; n && *l==*r && *l && *r; l++, r++);
+       return n ? *l - *r : 0;
+}
diff --git a/src/string/wcsncpy.c b/src/string/wcsncpy.c
new file mode 100644 (file)
index 0000000..0164208
--- /dev/null
@@ -0,0 +1,9 @@
+#include <wchar.h>
+
+wchar_t *wcsncpy(wchar_t *d, const wchar_t *s, size_t n)
+{
+       wchar_t *a = d;
+       while (n && (*d++ = *s++)) n--;
+       wmemset(d, 0, n);
+       return a;
+}
diff --git a/src/string/wcspbrk.c b/src/string/wcspbrk.c
new file mode 100644 (file)
index 0000000..0c72c19
--- /dev/null
@@ -0,0 +1,7 @@
+#include <wchar.h>
+
+wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b)
+{
+       s += wcscspn(s, b);
+       return *s ? (wchar_t *)s : NULL;
+}
diff --git a/src/string/wcsrchr.c b/src/string/wcsrchr.c
new file mode 100644 (file)
index 0000000..7503475
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+wchar_t *wcsrchr(const wchar_t *s, wint_t c)
+{
+       const wchar_t *p;
+       for (p=s+wcslen(s); p>=s && *p!=c; p--);
+       return p>=s ? (wchar_t *)p : 0;
+}
diff --git a/src/string/wcsspn.c b/src/string/wcsspn.c
new file mode 100644 (file)
index 0000000..4320d8f
--- /dev/null
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+size_t wcsspn(const wchar_t *s, const wchar_t *c)
+{
+       const wchar_t *a;
+       for (a=s; *s && wcschr(c, *s); s++);
+       return s-a;
+}
diff --git a/src/string/wcsstr.c b/src/string/wcsstr.c
new file mode 100644 (file)
index 0000000..966174f
--- /dev/null
@@ -0,0 +1,117 @@
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+static wchar_t *naive_wcsstr(const wchar_t *h, const wchar_t *n)
+{
+       size_t i;
+       for (i=0; n[i] && h[i]; i++)
+       for (   ; n[i] != h[i]; h++, i=0);
+       return n[i] ? 0 : (wchar_t *)h;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
+{
+       const wchar_t *z;
+       size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+
+       /* Computing length of needle */
+       for (l=0; n[l] && h[l]; l++);
+       if (n[l]) return 0; /* hit the end of h */
+
+       /* Compute maximal suffix */
+       ip = -1; jp = 0; k = p = 1;
+       while (jp+k<l) {
+               if (n[ip+k] == n[jp+k]) {
+                       if (k == p) {
+                               jp += p;
+                               k = 1;
+                       } else k++;
+               } else if (n[ip+k] > n[jp+k]) {
+                       jp += k;
+                       k = 1;
+                       p = jp - ip;
+               } else {
+                       ip = jp++;
+                       k = p = 1;
+               }
+       }
+       ms = ip;
+       p0 = p;
+
+       /* And with the opposite comparison */
+       ip = -1; jp = 0; k = p = 1;
+       while (jp+k<l) {
+               if (n[ip+k] == n[jp+k]) {
+                       if (k == p) {
+                               jp += p;
+                               k = 1;
+                       } else k++;
+               } else if (n[ip+k] < n[jp+k]) {
+                       jp += k;
+                       k = 1;
+                       p = jp - ip;
+               } else {
+                       ip = jp++;
+                       k = p = 1;
+               }
+       }
+       if (ip+1 > ms+1) ms = ip;
+       else p = p0;
+
+       /* Periodic needle? */
+       if (wmemcmp(n, n+p, ms+1)) {
+               mem0 = 0;
+               p = MAX(ms, l-ms-1) + 1;
+       } else mem0 = l-p;
+       mem = 0;
+
+       /* Initialize incremental end-of-haystack pointer */
+       z = h;
+
+       /* Search loop */
+       for (;;) {
+               /* Update incremental end-of-haystack pointer */
+               if (z-h < l) {
+                       /* Fast estimate for MIN(l,63) */
+                       size_t grow = l | 63;
+                       const wchar_t *z2 = wmemchr(z, 0, grow);
+                       if (z2) {
+                               z = z2;
+                               if (z-h < l) return 0;
+                       } else z += grow;
+               }
+
+               /* Compare right half */
+               for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+               if (n[k]) {
+                       h += k-ms;
+                       mem = 0;
+                       continue;
+               }
+               /* Compare left half */
+               for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+               if (k == mem) return (wchar_t *)h;
+               h += p;
+               mem = mem0;
+       }
+}
+
+wchar_t *wcsstr(const wchar_t *h, const wchar_t *n)
+{
+       /* Return immediately on empty needle or haystack */
+       if (!n[0]) return (wchar_t *)h;
+       if (!h[0]) return 0;
+
+       /* Use faster algorithms for short needles */
+       h = wcschr(h, *n);
+       if (!h || !n[1]) return (wchar_t *)h;
+       if (!h[1]) return 0;
+       if (!n[2] || !n[3] || !n[4]) return naive_wcsstr(h, n);
+
+       return twoway_wcsstr(h, n);
+}
diff --git a/src/string/wcswcs.c b/src/string/wcswcs.c
new file mode 100644 (file)
index 0000000..9cfe4ac
--- /dev/null
@@ -0,0 +1,6 @@
+#include <wchar.h>
+
+wchar_t *wcswcs(const wchar_t *haystack, const wchar_t *needle)
+{
+       return wcsstr(haystack, needle);
+}
diff --git a/src/string/wmemchr.c b/src/string/wmemchr.c
new file mode 100644 (file)
index 0000000..a3ee0e6
--- /dev/null
@@ -0,0 +1,8 @@
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n)
+{
+       for (; n && *s != c; s++);
+       return n ? (wchar_t *)s : 0;
+}
diff --git a/src/string/wmemcmp.c b/src/string/wmemcmp.c
new file mode 100644 (file)
index 0000000..6788a38
--- /dev/null
@@ -0,0 +1,8 @@
+#include <string.h>
+#include <wchar.h>
+
+int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n)
+{
+       for (; n && *l==*r; n--, l++, r++);
+       return n ? *l-*r : 0;
+}
diff --git a/src/string/wmemcpy.c b/src/string/wmemcpy.c
new file mode 100644 (file)
index 0000000..330e37c
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *wmemcpy(wchar_t *d, const wchar_t *s, size_t n)
+{
+       wchar_t *a = d;
+       while (n--) *d++ = *s++;
+       return a;
+}
diff --git a/src/string/wmemmove.c b/src/string/wmemmove.c
new file mode 100644 (file)
index 0000000..49608ca
--- /dev/null
@@ -0,0 +1,11 @@
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n)
+{
+       if ((size_t)(d-s) < n) {
+               while (n--) d[n] = s[n];
+               return d;
+       }
+       return wmemcpy(d, s, n);
+}
diff --git a/src/string/wmemset.c b/src/string/wmemset.c
new file mode 100644 (file)
index 0000000..1a2a861
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *wmemset(wchar_t *d, wchar_t c, size_t n)
+{
+       wchar_t *ret = d;
+       while (n--) *d++ = c;
+       return ret;
+}
diff --git a/src/stub/utmpx.c b/src/stub/utmpx.c
new file mode 100644 (file)
index 0000000..3200396
--- /dev/null
@@ -0,0 +1,30 @@
+#include <utmpx.h>
+#include <stddef.h>
+
+void endutxent(void)
+{
+}
+
+void setutxent(void)
+{
+}
+
+struct utmpx *getutxent(void)
+{
+       return NULL;
+}
+
+struct utmpx *getutxid(const struct utmpx *ut)
+{
+       return NULL;
+}
+
+struct utmpx *getutxline(const struct utmpx *ut)
+{
+       return NULL;
+}
+
+struct utmpx *pututxline(const struct utmpx *ut)
+{
+       return NULL;
+}
diff --git a/src/temp/mkdtemp.c b/src/temp/mkdtemp.c
new file mode 100644 (file)
index 0000000..f8b067e
--- /dev/null
@@ -0,0 +1,21 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include "libc.h"
+
+char *mkdtemp(char *template)
+{
+       for (;;) {
+               if (!mktemp(template)) return 0;
+               if (!mkdir(template, 0700)) return template;
+               if (errno != EEXIST) return 0;
+               /* this is safe because mktemp verified
+                * that we have a valid template string */
+               strcpy(template+strlen(template)-6, "XXXXXX");
+       }
+}
diff --git a/src/temp/mkstemp.c b/src/temp/mkstemp.c
new file mode 100644 (file)
index 0000000..b156719
--- /dev/null
@@ -0,0 +1,26 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include "libc.h"
+
+int mkstemp(char *template)
+{
+       int fd;
+retry:
+       if (!mktemp(template)) return -1;
+       fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
+       if (fd >= 0) return fd;
+       if (errno == EEXIST) {
+               /* this is safe because mktemp verified
+                * that we have a valid template string */
+               strcpy(template+strlen(template)-6, "XXXXXX");
+               goto retry;
+       }
+       return -1;
+}
+
+LFS64(mkstemp);
diff --git a/src/temp/mktemp.c b/src/temp/mktemp.c
new file mode 100644 (file)
index 0000000..8638e08
--- /dev/null
@@ -0,0 +1,29 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "libc.h"
+
+char *mktemp(char *template)
+{
+       static int lock;
+       static int index;
+       int l = strlen(template);
+
+       if (l < 6 || strcmp(template+l-6, "XXXXXX")) {
+               errno = EINVAL;
+               return NULL;
+       }
+       LOCK(&lock);
+       for (; index < 1000000; index++) {
+               snprintf(template+l-6, 6, "%06d", index);
+               if (access(template, F_OK) != 0) {
+                       UNLOCK(&lock);
+                       return template;
+               }
+       }
+       UNLOCK(&lock);
+       return NULL;    
+}
diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c
new file mode 100644 (file)
index 0000000..0ebc198
--- /dev/null
@@ -0,0 +1,12 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+
+speed_t cfgetospeed(const struct termios *tio)
+{
+       return tio->c_cflag & CBAUD;
+}
+
+speed_t cfgetispeed(const struct termios *tio)
+{
+       return cfgetospeed(tio);
+}
diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c
new file mode 100644 (file)
index 0000000..80c790f
--- /dev/null
@@ -0,0 +1,22 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include "libc.h"
+
+int cfsetospeed(struct termios *tio, speed_t speed)
+{
+       if (speed & ~CBAUD) {
+               errno = EINVAL;
+               return -1;
+       }
+       tio->c_cflag &= ~CBAUD;
+       tio->c_cflag |= speed;
+       return 0;
+}
+
+int cfsetispeed(struct termios *tio, speed_t speed)
+{
+       return speed ? cfsetospeed(tio, speed) : 0;
+}
+
+weak_alias(cfsetospeed, cfsetspeed);
diff --git a/src/termios/tcdrain.c b/src/termios/tcdrain.c
new file mode 100644 (file)
index 0000000..c51dd40
--- /dev/null
@@ -0,0 +1,7 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcdrain(int fd)
+{
+       return ioctl(fd, TCSBRK, 1);
+}
diff --git a/src/termios/tcflow.c b/src/termios/tcflow.c
new file mode 100644 (file)
index 0000000..c7fc3fe
--- /dev/null
@@ -0,0 +1,7 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcflow(int fd, int action)
+{
+       return ioctl(fd, TCXONC, action);
+}
diff --git a/src/termios/tcflush.c b/src/termios/tcflush.c
new file mode 100644 (file)
index 0000000..5022266
--- /dev/null
@@ -0,0 +1,7 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcflush(int fd, int queue)
+{
+       return ioctl(fd, TCFLSH, queue);
+}
diff --git a/src/termios/tcgetattr.c b/src/termios/tcgetattr.c
new file mode 100644 (file)
index 0000000..d9ce786
--- /dev/null
@@ -0,0 +1,10 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+int tcgetattr(int fd, struct termios *tio)
+{
+       if (ioctl(fd, TCGETS, tio))
+               return -1;
+       return 0;
+}
diff --git a/src/termios/tcgetsid.c b/src/termios/tcgetsid.c
new file mode 100644 (file)
index 0000000..1053fd6
--- /dev/null
@@ -0,0 +1,10 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+
+pid_t tcgetsid(int fd)
+{
+       int sid;
+       if (ioctl(fd, TIOCGSID, &sid) < 0)
+               return -1;
+       return sid;
+}
diff --git a/src/termios/tcsendbreak.c b/src/termios/tcsendbreak.c
new file mode 100644 (file)
index 0000000..b6df0a2
--- /dev/null
@@ -0,0 +1,8 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcsendbreak(int fd, int dur)
+{
+       /* nonzero duration is implementation-defined, so ignore it */
+       return ioctl(fd, TCSBRK, 0);
+}
diff --git a/src/termios/tcsetattr.c b/src/termios/tcsetattr.c
new file mode 100644 (file)
index 0000000..e9a168f
--- /dev/null
@@ -0,0 +1,13 @@
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <errno.h>
+
+int tcsetattr(int fd, int act, const struct termios *tio)
+{
+       if (act < 0 || act > 2) {
+               errno = EINVAL;
+               return -1;
+       }
+       return ioctl(fd, TCSETS+act, tio);
+}
diff --git a/src/thread/__futex.c b/src/thread/__futex.c
new file mode 100644 (file)
index 0000000..93352fa
--- /dev/null
@@ -0,0 +1,8 @@
+#include "futex.h"
+#include "syscall.h"
+
+int __futex(volatile int *addr, int op, int val, void *ts)
+{
+       return syscall4(__NR_futex, (long)addr, op, val, (long)ts);
+}
+
diff --git a/src/thread/__lock.c b/src/thread/__lock.c
new file mode 100644 (file)
index 0000000..557c6a6
--- /dev/null
@@ -0,0 +1,12 @@
+#define SYSCALL_RETURN_ERRNO
+#include "pthread_impl.h"
+
+void __lock(volatile int *l)
+{
+       int spins=100000;
+       /* Do not use futexes because we insist that unlocking is a simple
+        * assignment to optimize non-pathological code with no contention. */
+       while (a_xchg(l, 1))
+               if (spins) spins--, a_spin();
+               else syscall0(__NR_sched_yield);
+}
diff --git a/src/thread/__set_thread_area.c b/src/thread/__set_thread_area.c
new file mode 100644 (file)
index 0000000..576d8b4
--- /dev/null
@@ -0,0 +1,9 @@
+#include "syscall.h"
+
+int __set_thread_area(unsigned long *desc)
+{
+       if (syscall1(__NR_set_thread_area, (long)desc) < 0)
+               return -1;
+       __asm__ __volatile__ ( "movw %w0,%%gs" : : "r"(desc[0]*8+3) );
+       return 0;
+}
diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c
new file mode 100644 (file)
index 0000000..354def2
--- /dev/null
@@ -0,0 +1,21 @@
+#include <time.h>
+#include <errno.h>
+#include "futex.h"
+#define SYSCALL_RETURN_ERRNO
+#include "syscall.h"
+#include <stdio.h>
+int __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv)
+{
+       struct timespec to;
+       if (at) {
+               clock_gettime(clk, &to);
+               to.tv_sec = at->tv_sec - to.tv_sec;
+               if ((to.tv_nsec = at->tv_nsec - to.tv_nsec) < 0) {
+                       to.tv_sec--;
+                       to.tv_nsec += 1000000000;
+               }
+               if (to.tv_sec < 0) return ETIMEDOUT;
+       }
+       if (priv) priv = 128; priv=0;
+       return syscall4(__NR_futex, (long)addr, FUTEX_WAIT | priv, val, at ? (long)&to : 0);
+}
diff --git a/src/thread/__unmapself.c b/src/thread/__unmapself.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/thread/__wait.c b/src/thread/__wait.c
new file mode 100644 (file)
index 0000000..8c249cd
--- /dev/null
@@ -0,0 +1,16 @@
+#define SYSCALL_RETURN_ERRNO
+#include "pthread_impl.h"
+
+void __wait(volatile int *addr, volatile int *waiters, int val, int priv)
+{
+       int spins=50000;
+       if (priv) priv = 128; priv=0;
+       while (spins--) {
+               if (*addr==val) a_spin();
+               else return;
+       }
+       if (waiters) a_inc(waiters);
+       while (*addr==val)
+               syscall4(__NR_futex, (long)addr, FUTEX_WAIT|priv, val, 0);
+       if (waiters) a_dec(waiters);
+}
diff --git a/src/thread/__wake.c b/src/thread/__wake.c
new file mode 100644 (file)
index 0000000..048ddcc
--- /dev/null
@@ -0,0 +1,9 @@
+#define SYSCALL_RETURN_ERRNO
+#include "pthread_impl.h"
+
+void __wake(volatile int *addr, int cnt, int priv)
+{
+       if (priv) priv = 128; priv=0;
+       if (cnt<0) cnt = INT_MAX;
+       syscall3(__NR_futex, (long)addr, FUTEX_WAKE | priv, cnt);
+}
diff --git a/src/thread/cancellation.c b/src/thread/cancellation.c
new file mode 100644 (file)
index 0000000..e35ba82
--- /dev/null
@@ -0,0 +1,22 @@
+#include "pthread_impl.h"
+
+void __pthread_register_cancel(struct __ptcb *cb)
+{
+       struct pthread *self = pthread_self();
+       cb->__next = self->cancelbuf;
+       self->cancelbuf = cb;
+}
+
+#define pthread_self __pthread_self
+
+void __pthread_unregister_cancel(struct __ptcb *cb)
+{
+       struct pthread *self = pthread_self();
+       self->cancelbuf = self->cancelbuf->__next;
+}
+
+void __pthread_unwind_next(struct __ptcb *cb)
+{
+       if (cb->__next) longjmp((void *)cb->__next->__jb, 1);
+       pthread_exit(PTHREAD_CANCELLED);
+}
diff --git a/src/thread/clone.c b/src/thread/clone.c
new file mode 100644 (file)
index 0000000..971bfee
--- /dev/null
@@ -0,0 +1,26 @@
+#if 0
+
+int clone(int (*start)(void *), void *stack, int flags, void *arg,
+       pid_t *ptid, struct user_desc *tls, pid_t *ctid)
+{
+       int ret;
+       __asm__(
+               "andl $-16,%%ecx     \n\t"
+               "xchgl %%ebx,%2      \n\t"
+               "movl %%ebx,(%%ecx)  \n\t"
+               "int $0x80           \n\t"
+               "testl %%eax,%%eax   \n\t"
+               "jnz 1f              \n\t"
+               "xorl %%ebp,%%ebp    \n\t"
+               "call *%%ebx         \n\t"
+               "\n1:                \n\t"
+               "xchgl %%ebx,%2      \n\t"
+               : "=a" (ret)
+               : "a" (__NR_clone), "m" (flags), "c"(stack), "d"(ptid),
+                 "S" (tls), "D" (ctid)
+               : "memory"
+       );
+       return __syscall_ret(ret);
+}
+
+#endif
diff --git a/src/thread/i386/__unmapself.s b/src/thread/i386/__unmapself.s
new file mode 100644 (file)
index 0000000..5c67496
--- /dev/null
@@ -0,0 +1,22 @@
+.text
+.global __unmapself
+.type   __unmapself,%function
+__unmapself:
+       call 1f
+       .long -1
+       .long -1
+1:     popl %ecx
+       xorl %ebx,%ebx
+       xorl %edx,%edx
+       movl $8,%esi
+       movl $175,%eax
+       int $128
+       movl $91,%eax
+       movl 4(%esp),%ebx
+       movl 8(%esp),%ecx
+       int $128
+       xorl %ebx,%ebx
+       movl $1,%eax
+       int $128
+
+.size __unmapself,.-__unmapself
diff --git a/src/thread/i386/clone.s b/src/thread/i386/clone.s
new file mode 100644 (file)
index 0000000..4f33366
--- /dev/null
@@ -0,0 +1,35 @@
+.text
+.global __clone
+.type   __clone,%function
+__clone:
+       movl    8(%esp),%ecx
+       andl    $0xfffffff0, %ecx
+       subl    $28,%ecx
+       movl    16(%esp),%eax
+       movl    %eax,12(%ecx)
+       movl    4(%esp),%eax
+       movl    %eax,8(%ecx)
+       pushl   %ebx
+       pushl   %esi
+       pushl   %edi
+       movl    $120,%eax
+       movl    12+12(%esp),%ebx
+       movl    20+12(%esp),%edx
+       movl    24+12(%esp),%esi
+       movl    28+12(%esp),%edi
+       int     $128
+       popl    %edi
+       popl    %esi
+       popl    %ebx
+       test    %eax,%eax
+       jnz     1f
+       xorl    %ebp,%ebp
+       call    *%ebx
+       movl    %eax, %ebx
+       movl    $1, %eax
+       int     $128
+1:     
+       movl %eax, 4(%esp)
+       ret
+
+.size __clone,.-__clone
diff --git a/src/thread/pthread_attr_destroy.c b/src/thread/pthread_attr_destroy.c
new file mode 100644 (file)
index 0000000..b5845dd
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_attr_destroy(pthread_attr_t *a)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_attr_getdetachstate.c b/src/thread/pthread_attr_getdetachstate.c
new file mode 100644 (file)
index 0000000..9cd4953
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_getdetachstate(pthread_attr_t *a, int *state)
+{
+       *state = a->__detach;
+       return 0;
+}
diff --git a/src/thread/pthread_attr_getguardsize.c b/src/thread/pthread_attr_getguardsize.c
new file mode 100644 (file)
index 0000000..3f089c8
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_getguardsize(pthread_attr_t *a, size_t *size)
+{
+       *size = a->__guardsize + DEFAULT_GUARD_SIZE;
+       return 0;
+}
diff --git a/src/thread/pthread_attr_getscope.c b/src/thread/pthread_attr_getscope.c
new file mode 100644 (file)
index 0000000..0cb224d
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_attr_getscope(pthread_attr_t *a, int *scope)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_attr_getstacksize.c b/src/thread/pthread_attr_getstacksize.c
new file mode 100644 (file)
index 0000000..40bbf18
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_getstacksize(pthread_attr_t *a, size_t *size)
+{
+       *size = a->__stacksize + DEFAULT_STACK_SIZE;
+       return 0;
+}
diff --git a/src/thread/pthread_attr_init.c b/src/thread/pthread_attr_init.c
new file mode 100644 (file)
index 0000000..d91bf15
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_init(pthread_attr_t *a)
+{
+       memset(a, 0, sizeof *a);
+       return 0;
+}
diff --git a/src/thread/pthread_attr_setdetachstate.c b/src/thread/pthread_attr_setdetachstate.c
new file mode 100644 (file)
index 0000000..d23b477
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setdetachstate(pthread_attr_t *a, int state)
+{
+       a->__detach = state;
+       return 0;
+}
diff --git a/src/thread/pthread_attr_setguardsize.c b/src/thread/pthread_attr_setguardsize.c
new file mode 100644 (file)
index 0000000..e0e8d3f
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setguardsize(pthread_attr_t *a, size_t size)
+{
+       if (size > SIZE_MAX/8) return EINVAL;
+       a->__guardsize = size - DEFAULT_GUARD_SIZE;
+       return 0;
+}
diff --git a/src/thread/pthread_attr_setscope.c b/src/thread/pthread_attr_setscope.c
new file mode 100644 (file)
index 0000000..a970a81
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setscope(pthread_attr_t *a, int scope)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_attr_setstacksize.c b/src/thread/pthread_attr_setstacksize.c
new file mode 100644 (file)
index 0000000..58f4bb1
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setstacksize(pthread_attr_t *a, size_t size)
+{
+       if (size-PAGE_SIZE > SIZE_MAX/4) return EINVAL;
+       a->__stacksize = size - DEFAULT_STACK_SIZE;
+       return 0;
+}
diff --git a/src/thread/pthread_barrier_destroy.c b/src/thread/pthread_barrier_destroy.c
new file mode 100644 (file)
index 0000000..2898c41
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_barrier_destroy(pthread_barrier_t *b)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_barrier_init.c b/src/thread/pthread_barrier_init.c
new file mode 100644 (file)
index 0000000..2cc67ed
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_barrier_init(pthread_barrier_t *b, const pthread_barrierattr_t *a, unsigned count)
+{
+       if (!count) return EINVAL;
+       *b = (pthread_barrier_t){ .__limit = count-1 };
+       return 0;
+}
diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c
new file mode 100644 (file)
index 0000000..02c252a
--- /dev/null
@@ -0,0 +1,31 @@
+#include "pthread_impl.h"
+
+int pthread_barrier_wait(pthread_barrier_t *b)
+{
+       int cur;
+
+       /* Trivial case: count was set at 1 */
+       if (!b->__limit) return PTHREAD_BARRIER_SERIAL_THREAD;
+
+       /* Wait for anyone still suspended at previous use of barrier */
+       while ((cur=b->__left))
+               __wait(&b->__left, &b->__waiters, cur, 0);
+
+       /* If we are the last to reach barrier, reset it and wake others */
+       if (a_fetch_add(&b->__count, 1) == b->__limit) {
+               b->__left = b->__limit;
+               b->__count = 0;
+               __wake(&b->__count, -1, 0);
+               return PTHREAD_BARRIER_SERIAL_THREAD;
+       }
+
+       /* Wait for our peers to reach the barrier */
+       while ((cur=b->__count))
+               __wait(&b->__count, 0, cur, 0);
+
+       /* If we're the last to wake up and barrier is awaiting reuse */
+       if (a_fetch_add(&b->__left, -1) == 1 && b->__waiters)
+               __wake(&b->__left, -1, 0);
+
+       return 0;
+}
diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
new file mode 100644 (file)
index 0000000..9397ffe
--- /dev/null
@@ -0,0 +1,7 @@
+#define SYSCALL_RETURN_ERRNO
+#include "pthread_impl.h"
+
+int pthread_cancel(pthread_t t)
+{
+       return syscall3(__NR_tgkill, t->pid, t->tid, SIGCANCEL);
+}
diff --git a/src/thread/pthread_cond_broadcast.c b/src/thread/pthread_cond_broadcast.c
new file mode 100644 (file)
index 0000000..7a023b8
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_cond_broadcast(pthread_cond_t *c)
+{
+       c->__block = 0;
+       __wake(&c->__block, -1, 0);
+       return 0;
+}
diff --git a/src/thread/pthread_cond_destroy.c b/src/thread/pthread_cond_destroy.c
new file mode 100644 (file)
index 0000000..1d21a5a
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_cond_destroy(pthread_cond_t *c)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_cond_init.c b/src/thread/pthread_cond_init.c
new file mode 100644 (file)
index 0000000..3394860
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a)
+{
+       memset(c, 0, sizeof *c);
+       return 0;
+}
diff --git a/src/thread/pthread_cond_signal.c b/src/thread/pthread_cond_signal.c
new file mode 100644 (file)
index 0000000..0dd9416
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_cond_signal(pthread_cond_t *c)
+{
+       c->__block = 0;
+       __wake(&c->__block, 1, 0);
+       return 0;
+}
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c
new file mode 100644 (file)
index 0000000..b67dded
--- /dev/null
@@ -0,0 +1,26 @@
+#include "pthread_impl.h"
+
+static void relock(void *m)
+{
+       pthread_mutex_lock(m);
+}
+
+int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *ts)
+{
+       int r, e=0;
+       CANCELPT(0);
+
+       pthread_cleanup_push(relock, m);
+       c->__block = 1;
+       if ((r=pthread_mutex_unlock(m))) return r;
+
+       CANCELPT(1);
+       e = __timedwait(&c->__block, 1, CLOCK_REALTIME, ts, 0);
+       CANCELPT(0);
+
+       pthread_cleanup_pop(0);
+       if ((r=pthread_mutex_lock(m))) return r;
+
+       CANCELPT(0);
+       return e;
+}
diff --git a/src/thread/pthread_cond_wait.c b/src/thread/pthread_cond_wait.c
new file mode 100644 (file)
index 0000000..eb70e5f
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
+{
+       return pthread_cond_timedwait(c, m, 0);
+}
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
new file mode 100644 (file)
index 0000000..6fa484c
--- /dev/null
@@ -0,0 +1,189 @@
+#include "pthread_impl.h"
+
+#define pthread_self __pthread_self
+
+static void docancel(struct pthread *self)
+{
+       struct __ptcb cb = { .__next = self->cancelbuf };
+       __pthread_unwind_next(&cb);
+}
+
+static void cancel_handler(int sig, siginfo_t *si, void *ctx)
+{
+       struct pthread *self = pthread_self();
+       self->cancel = 1;
+       if (self->canceldisable || (!self->cancelasync && !self->cancelpoint))
+               return;
+       docancel(self);
+}
+
+/* "rsyscall" is a mechanism by which a thread can synchronously force all
+ * other threads to perform an arbitrary syscall. It is necessary to work
+ * around the non-conformant implementation of setuid() et al on Linux,
+ * which affect only the calling thread and not the whole process. This
+ * implementation performs some tricks with signal delivery to work around
+ * the fact that it does not keep any list of threads in userspace. */
+
+static struct {
+       volatile int lock, hold, blocks, cnt;
+       unsigned long arg[6];
+       int nr;
+       int err;
+} rs;
+
+static void rsyscall_handler(int sig, siginfo_t *si, void *ctx)
+{
+       if (rs.cnt == libc.threads_minus_1) return;
+
+       if (syscall6(rs.nr, rs.arg[0], rs.arg[1], rs.arg[2],
+               rs.arg[3], rs.arg[4], rs.arg[5]) < 0 && !rs.err) rs.err=errno;
+
+       a_inc(&rs.cnt);
+       __wake(&rs.cnt, 1, 1);
+       while(rs.hold)
+               __wait(&rs.hold, 0, 1, 1);
+       a_dec(&rs.cnt);
+       if (!rs.cnt) __wake(&rs.cnt, 1, 1);
+}
+
+static int rsyscall(int nr, long a, long b, long c, long d, long e, long f)
+{
+       int i, ret;
+       sigset_t set = { 0 };
+       struct pthread *self = pthread_self();
+       sigaddset(&set, SIGSYSCALL);
+
+       LOCK(&rs.lock);
+       while ((i=rs.blocks))
+               __wait(&rs.blocks, 0, i, 1);
+
+       __libc_sigprocmask(SIG_BLOCK, &set, 0);
+
+       rs.nr = nr;
+       rs.arg[0] = a; rs.arg[1] = b;
+       rs.arg[2] = c; rs.arg[3] = d;
+       rs.arg[4] = d; rs.arg[5] = f;
+       rs.hold = 1;
+       rs.err = 0;
+       rs.cnt = 0;
+
+       /* Dispatch signals until all threads respond */
+       for (i=libc.threads_minus_1; i; i--)
+               sigqueue(self->pid, SIGSYSCALL, (union sigval){0});
+       while ((i=rs.cnt) < libc.threads_minus_1) {
+               sigqueue(self->pid, SIGSYSCALL, (union sigval){0});
+               __wait(&rs.cnt, 0, i, 1);
+       }
+
+       /* Handle any lingering signals with no-op */
+       __libc_sigprocmask(SIG_UNBLOCK, &set, 0);
+
+       /* Resume other threads' signal handlers and wait for them */
+       rs.hold = 0;
+       __wake(&rs.hold, -1, 0);
+       while((i=rs.cnt)) __wait(&rs.cnt, 0, i, 1);
+
+       if (rs.err) errno = rs.err, ret = -1;
+       else ret = syscall6(nr, a, b, c, d, e, f);
+
+       UNLOCK(&rs.lock);
+       return ret;
+}
+
+static void cancelpt(int x)
+{
+       struct pthread *self = pthread_self();
+       if (self->canceldisable) return;
+       self->cancelpoint = x;
+       if (self->cancel) docancel(self);
+}
+
+static void init_threads()
+{
+       struct sigaction sa = { .sa_flags = SA_SIGINFO | SA_RESTART };
+       libc.lock = __lock;
+       libc.cancelpt = cancelpt;
+       libc.rsyscall = rsyscall;
+       sa.sa_sigaction = cancel_handler;
+       __libc_sigaction(SIGCANCEL, &sa, 0);
+       sigaddset(&sa.sa_mask, SIGSYSCALL);
+       sigaddset(&sa.sa_mask, SIGCANCEL);
+       sa.sa_sigaction = rsyscall_handler;
+       __libc_sigaction(SIGSYSCALL, &sa, 0);
+       sigprocmask(SIG_UNBLOCK, &sa.sa_mask, 0);
+}
+
+static int start(void *p)
+{
+       struct pthread *self = p;
+       pthread_exit(self->start(self->start_arg));
+       return 0;
+}
+
+#undef pthread_self
+
+#define CLONE_MAGIC 0x7d0f00
+int __clone(int (*)(void *), void *, int, void *, pid_t *, void *, pid_t *);
+
+#define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
+
+/* pthread_key_create.c overrides this */
+static const size_t dummy = 0;
+weak_alias(dummy, __pthread_tsd_size);
+
+int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(void *), void *arg)
+{
+       static int init;
+       int ret;
+       size_t size, guard;
+       struct pthread *self = pthread_self(), *new;
+       unsigned char *map, *stack, *tsd;
+       static const pthread_attr_t default_attr;
+
+       if (!self) return errno = ENOSYS;
+       if (!init && ++init) init_threads();
+
+       if (!attr) attr = &default_attr;
+       guard = ROUND(attr->__guardsize + DEFAULT_GUARD_SIZE);
+       size = guard + ROUND(attr->__stacksize + DEFAULT_STACK_SIZE);
+       size += __pthread_tsd_size;
+       map = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
+       if (!map) return EAGAIN;
+       mprotect(map, guard, PROT_NONE);
+
+       tsd = map + size - __pthread_tsd_size;
+       new = (void *)(tsd - sizeof *new - PAGE_SIZE%sizeof *new);
+       new->map_base = map;
+       new->map_size = size;
+       new->pid = self->pid;
+       new->errno_ptr = &new->errno_val;
+       new->start = entry;
+       new->start_arg = arg;
+       new->self = new;
+       new->tsd = (void *)tsd;
+       new->detached = attr->__detach;
+       new->attr = *attr;
+       memcpy(new->tlsdesc, self->tlsdesc, sizeof new->tlsdesc);
+       new->tlsdesc[1] = (uintptr_t)new;
+       stack = (void *)((uintptr_t)new-1 & ~(uintptr_t)15);
+
+       /* We must synchronize new thread creation with rsyscall
+        * delivery. This looks to be the least expensive way: */
+       a_inc(&rs.blocks);
+       while (rs.lock) __wait(&rs.lock, 0, 1, 1);
+
+       a_inc(&libc.threads_minus_1);
+       ret = __clone(start, stack, CLONE_MAGIC, new,
+               &new->tid, &new->tlsdesc, &new->tid);
+
+       a_dec(&rs.blocks);
+       if (rs.lock) __wake(&rs.blocks, 1, 1);
+
+       if (ret < 0) {
+               a_dec(&libc.threads_minus_1);
+               munmap(map, size);
+               return -ret;
+       }
+       *res = new;
+       return 0;
+}
diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c
new file mode 100644 (file)
index 0000000..f0eae3e
--- /dev/null
@@ -0,0 +1,11 @@
+#include "pthread_impl.h"
+
+int pthread_detach(pthread_t t)
+{
+       /* Cannot detach a thread that's already exiting */
+       if (a_xchg(&t->exitlock, 1))
+               return pthread_join(t, 0);
+       t->detached = 1;
+       t->exitlock = 0;
+       return 0;
+}
diff --git a/src/thread/pthread_equal.c b/src/thread/pthread_equal.c
new file mode 100644 (file)
index 0000000..a55d280
--- /dev/null
@@ -0,0 +1,6 @@
+#include <pthread.h>
+
+int pthread_equal(pthread_t a, pthread_t b)
+{
+       return a==b;
+}
diff --git a/src/thread/pthread_exit.c b/src/thread/pthread_exit.c
new file mode 100644 (file)
index 0000000..4966e23
--- /dev/null
@@ -0,0 +1,25 @@
+#include "pthread_impl.h"
+
+#undef pthread_self
+
+void pthread_exit(void *result)
+{
+       int i;
+       struct pthread *self = pthread_self();
+       self->result = result;
+
+       a_dec(&libc.threads_minus_1);
+       if (libc.threads_minus_1 < 0)
+               exit(0);
+
+       LOCK(&self->exitlock);
+
+       if (self->tsd_used) for (i=0; i<PTHREAD_KEYS_MAX; i++)
+               if (self->tsd[i] && libc.tsd_keys[i])
+                       libc.tsd_keys[i](self->tsd[i]);
+
+       if (self->detached && self->map_base)
+               __unmapself(self->map_base, self->map_size);
+
+       __syscall_exit(0);
+}
diff --git a/src/thread/pthread_getspecific.c b/src/thread/pthread_getspecific.c
new file mode 100644 (file)
index 0000000..a6ca27d
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+void *pthread_getspecific(pthread_key_t k)
+{
+       struct pthread *self = pthread_self();
+       if (!self->tsd) return 0;
+       return self->tsd[k];
+}
diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c
new file mode 100644 (file)
index 0000000..5210ed4
--- /dev/null
@@ -0,0 +1,12 @@
+#include "pthread_impl.h"
+
+int pthread_join(pthread_t t, void **res)
+{
+       int tmp = t->tid;
+       CANCELPT_BEGIN;
+       if (tmp) __wait(&t->tid, 0, tmp, 1);
+       CANCELPT_END;
+       if (res) *res = t->result;
+       if (t->map_base) munmap(t->map_base, t->map_size);
+       return 0;
+}
diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c
new file mode 100644 (file)
index 0000000..efc3804
--- /dev/null
@@ -0,0 +1,25 @@
+#include "pthread_impl.h"
+
+const size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX;
+
+static void nodtor(void *dummy)
+{
+}
+
+int pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
+{
+       static void (*keys[PTHREAD_KEYS_MAX])(void *);
+       int i = (uintptr_t)&k / 16 % PTHREAD_KEYS_MAX;
+       int j = i;
+
+       libc.tsd_keys = keys;
+       if (!dtor) dtor = nodtor;
+       /* Cheap trick - &k cannot match any destructor pointer */
+       while (a_cas_p(keys+j, 0, &k)
+               && (j=(j+1)%PTHREAD_KEYS_MAX) != i);
+       if (keys[j] != (void (*)(void *))&k)
+               return EAGAIN;
+       keys[j] = dtor;
+       *k = j;
+       return 0;
+}
diff --git a/src/thread/pthread_key_delete.c b/src/thread/pthread_key_delete.c
new file mode 100644 (file)
index 0000000..4914ebb
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_key_delete(pthread_key_t k)
+{
+       if (libc.tsd_keys) libc.tsd_keys[k] = 0;
+       return 0;
+}
diff --git a/src/thread/pthread_kill.c b/src/thread/pthread_kill.c
new file mode 100644 (file)
index 0000000..9d85fa5
--- /dev/null
@@ -0,0 +1,7 @@
+#define SYSCALL_RETURN_ERRNO
+#include "pthread_impl.h"
+
+int pthread_kill(pthread_t t, int sig)
+{
+       return syscall3(__NR_tgkill, t->pid, t->tid, sig);
+}
diff --git a/src/thread/pthread_mutex_destroy.c b/src/thread/pthread_mutex_destroy.c
new file mode 100644 (file)
index 0000000..6d49e68
--- /dev/null
@@ -0,0 +1,6 @@
+#include <pthread.h>
+
+int pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_mutex_init.c b/src/thread/pthread_mutex_init.c
new file mode 100644 (file)
index 0000000..d453543
--- /dev/null
@@ -0,0 +1,9 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a)
+{
+       memset(m, 0, sizeof *m);
+       if (a) {
+       }
+       return 0;
+}
diff --git a/src/thread/pthread_mutex_lock.c b/src/thread/pthread_mutex_lock.c
new file mode 100644 (file)
index 0000000..6696f17
--- /dev/null
@@ -0,0 +1,9 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_lock(pthread_mutex_t *m)
+{
+       int r;
+       while ((r=pthread_mutex_trylock(m)) == EBUSY)
+               __wait(&m->__lock, &m->__waiters, 1, 0);
+       return r;
+}
diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c
new file mode 100644 (file)
index 0000000..5dfad94
--- /dev/null
@@ -0,0 +1,15 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *at)
+{
+       int r, w=0;
+       while ((r=pthread_mutex_trylock(m)) == EBUSY) {
+               if (!w) a_inc(&m->__waiters), w++;
+               if (__timedwait(&m->__lock, 1, CLOCK_REALTIME, at, 0) == ETIMEDOUT) {
+                       if (w) a_dec(&m->__waiters);
+                       return ETIMEDOUT;
+               }
+       }
+       if (w) a_dec(&m->__waiters);
+       return r;
+}
diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c
new file mode 100644 (file)
index 0000000..1e3817b
--- /dev/null
@@ -0,0 +1,28 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_trylock(pthread_mutex_t *m)
+{
+       if (m->__type == PTHREAD_MUTEX_RECURSIVE) {
+               pthread_t self = pthread_self();
+               if (m->__owner == self) {
+                       if ((unsigned)m->__lock >= INT_MAX) return EAGAIN;
+                       a_inc(&m->__lock);
+                       return 0;
+               }
+               if (a_fetch_add(&m->__lock, 1)) {
+                       if (a_fetch_add(&m->__lock, -1)==1 && m->__waiters)
+                               __wake(&m->__lock, 1, 0);
+                       return EBUSY;
+               }
+               m->__owner = self;
+               return 0;
+       }
+
+       if (a_xchg(&m->__lock, 1))
+               if (m->__type == PTHREAD_MUTEX_ERRORCHECK
+                && m->__owner == pthread_self()) return EDEADLK;
+               else return EBUSY;
+       if (m->__type == PTHREAD_MUTEX_ERRORCHECK)
+               m->__owner = pthread_self();
+       return 0;
+}
diff --git a/src/thread/pthread_mutex_unlock.c b/src/thread/pthread_mutex_unlock.c
new file mode 100644 (file)
index 0000000..23e64ac
--- /dev/null
@@ -0,0 +1,19 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_unlock(pthread_mutex_t *m)
+{
+       if (m->__type == PTHREAD_MUTEX_RECURSIVE) {
+               if (a_fetch_add(&m->__lock, -1)==1 && m->__waiters)
+                       __wake(&m->__lock, 1, 0);
+               return 0;
+       }
+
+       if (m->__type == PTHREAD_MUTEX_ERRORCHECK
+        && m->__owner != pthread_self())
+               return EPERM;
+
+       m->__owner = 0;
+       m->__lock = 0;
+       if (m->__waiters) __wake(&m->__lock, 1, 0);
+       return 0;
+}
diff --git a/src/thread/pthread_mutexattr_destroy.c b/src/thread/pthread_mutexattr_destroy.c
new file mode 100644 (file)
index 0000000..9fd6974
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_mutexattr_gettype.c b/src/thread/pthread_mutexattr_gettype.c
new file mode 100644 (file)
index 0000000..9edb16c
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *a, int *type)
+{
+       *type = *a & 3;
+       return 0;
+}
diff --git a/src/thread/pthread_mutexattr_init.c b/src/thread/pthread_mutexattr_init.c
new file mode 100644 (file)
index 0000000..ea63106
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_mutexattr_init(pthread_mutexattr_t *a)
+{
+       memset(a, 0, sizeof *a);
+       return 0;
+}
diff --git a/src/thread/pthread_mutexattr_settype.c b/src/thread/pthread_mutexattr_settype.c
new file mode 100644 (file)
index 0000000..4e85950
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
+{
+       if ((unsigned)type > 2) return EINVAL;
+       *a = (*a & ~3) | type;
+       return 0;
+}
diff --git a/src/thread/pthread_once.c b/src/thread/pthread_once.c
new file mode 100644 (file)
index 0000000..7223005
--- /dev/null
@@ -0,0 +1,38 @@
+#include "pthread_impl.h"
+
+static void undo(void *control)
+{
+       a_store(control, 0);
+       __wake(control, 1, 0);
+}
+
+int pthread_once(pthread_once_t *control, void (*init)(void))
+{
+       static int waiters;
+
+       /* Return immediately if init finished before */
+       if (*control == 2) return 0;
+
+       /* Try to enter initializing state. Three possibilities:
+        *  0 - we're the first or the other cancelled; run init
+        *  1 - another thread is running init; wait
+        *  2 - another thread finished running init; just return */
+
+       for (;;) switch (a_swap(control, 1)) {
+       case 0:
+               break;
+       case 1:
+               __wait(control, &waiters, 1, 0);
+               continue;
+       case 2:
+               a_store(control, 2);
+               return 0;
+       }
+
+       pthread_cleanup_push(undo, control);
+       init();
+       pthread_cleanup_pop(0);
+
+       if (waiters) __wake(control, -1, 0);
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_destroy.c b/src/thread/pthread_rwlock_destroy.c
new file mode 100644 (file)
index 0000000..49ecfbd
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_destroy(pthread_rwlock_t *rw)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_init.c b/src/thread/pthread_rwlock_init.c
new file mode 100644 (file)
index 0000000..f87d566
--- /dev/null
@@ -0,0 +1,9 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_init(pthread_rwlock_t *rw, const pthread_rwlockattr_t *a)
+{
+       memset(rw, 0, sizeof *rw);
+       if (a) {
+       }
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_rdlock.c b/src/thread/pthread_rwlock_rdlock.c
new file mode 100644 (file)
index 0000000..6bcdb81
--- /dev/null
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rw)
+{
+       while (pthread_rwlock_tryrdlock(rw))
+               __wait(&rw->__wrlock, &rw->__waiters, 1, 0);
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_timedrdlock.c b/src/thread/pthread_rwlock_timedrdlock.c
new file mode 100644 (file)
index 0000000..290327d
--- /dev/null
@@ -0,0 +1,15 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *rw, const struct timespec *at)
+{
+       int w=0;
+       while (pthread_rwlock_tryrdlock(rw)) {
+               if (!w) a_inc(&rw->__waiters), w++;
+               if (__timedwait(&rw->__wrlock, 1, CLOCK_REALTIME, at, 0)==ETIMEDOUT) {
+                       if (w) a_dec(&rw->__waiters);
+                       return ETIMEDOUT;
+               }
+       }
+       if (w) a_dec(&rw->__waiters);
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c
new file mode 100644 (file)
index 0000000..9f74964
--- /dev/null
@@ -0,0 +1,17 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *rw, const struct timespec *at)
+{
+       int nr, *p, w=0;
+       while (pthread_rwlock_trywrlock(rw)==EAGAIN) {
+               if (!w) a_inc(&rw->__waiters), w++;
+               if ((nr=rw->__readers)) p = &rw->__readers;
+               else nr=1, p = &rw->__wrlock;
+               if (__timedwait(p, nr, CLOCK_REALTIME, at, 0)==ETIMEDOUT) {
+                       if (w) a_dec(&rw->__waiters);
+                       return ETIMEDOUT;
+               }
+       }
+       if (w) a_dec(&rw->__waiters);
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_tryrdlock.c b/src/thread/pthread_rwlock_tryrdlock.c
new file mode 100644 (file)
index 0000000..f59fbbd
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rw)
+{
+       a_inc(&rw->__readers);
+       if (rw->__wrlock) {
+               a_dec(&rw->__readers);
+               if (rw->__waiters && !rw->__readers)
+                       __wake(&rw->__readers, 1, 0);
+               return EAGAIN;
+       }
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_trywrlock.c b/src/thread/pthread_rwlock_trywrlock.c
new file mode 100644 (file)
index 0000000..c029b87
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rw)
+{
+       if (a_xchg(&rw->__wrlock, 1))
+               return EAGAIN;
+       if (rw->__readers) {
+               a_store(&rw->__wrlock, 0);
+               return EAGAIN;
+       }
+       rw->__owner = pthread_self()->tid;
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_unlock.c b/src/thread/pthread_rwlock_unlock.c
new file mode 100644 (file)
index 0000000..f39117e
--- /dev/null
@@ -0,0 +1,17 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rw)
+{
+       struct pthread *self = pthread_self();
+       if (rw->__owner == self->tid) {
+               rw->__owner = 0;
+               a_store(&rw->__wrlock, 0);
+               if (rw->__waiters)
+                       __wake(&rw->__wrlock, -1, 0);
+               return 0;
+       }
+       a_dec(&rw->__readers);
+       if (rw->__waiters && !rw->__readers)
+               __wake(&rw->__readers, 1, 0);
+       return 0;
+}
diff --git a/src/thread/pthread_rwlock_wrlock.c b/src/thread/pthread_rwlock_wrlock.c
new file mode 100644 (file)
index 0000000..219e924
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pthread_impl.h"
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rw)
+{
+       int nr;
+       while (pthread_rwlock_trywrlock(rw)==EAGAIN) {
+               if ((nr=rw->__readers))
+                       __wait(&rw->__readers, &rw->__waiters, nr, 0);
+               else
+                       __wait(&rw->__wrlock, &rw->__waiters, 1, 0);
+       }
+       return 0;
+}
diff --git a/src/thread/pthread_self.c b/src/thread/pthread_self.c
new file mode 100644 (file)
index 0000000..686d73d
--- /dev/null
@@ -0,0 +1,39 @@
+#include "pthread_impl.h"
+
+static struct pthread main_thread;
+
+#undef errno
+static int *errno_location()
+{
+       return pthread_self()->errno_ptr;
+}
+
+static int init_main_thread()
+{
+       main_thread.tlsdesc[0] = -1;
+       main_thread.tlsdesc[1] = (long)&main_thread;
+       main_thread.tlsdesc[2] = SIZE_MAX/PAGE_SIZE;
+       main_thread.tlsdesc[3] = 0x51;
+       main_thread.self = &main_thread;
+       main_thread.errno_ptr = __errno_location();
+       if (__set_thread_area(main_thread.tlsdesc) < 0)
+               return -1;
+       syscall1(__NR_set_tid_address, (long)&main_thread.tid);
+       libc.errno_location = errno_location;
+       main_thread.tid = main_thread.pid = getpid();
+       return 0;
+}
+
+#undef pthread_self
+
+pthread_t pthread_self()
+{
+       static int init, failed;
+       if (!init) {
+               if (failed) return 0;
+               if (init_main_thread() < 0) failed = 1;
+               if (failed) return 0;
+               init = 1;
+       }
+       return __pthread_self();
+}
diff --git a/src/thread/pthread_setcancelstate.c b/src/thread/pthread_setcancelstate.c
new file mode 100644 (file)
index 0000000..23c3885
--- /dev/null
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int pthread_setcancelstate(int new, int *old)
+{
+       struct pthread *self = pthread_self();
+       if (old) *old = self->canceldisable;
+       if ((unsigned)new > 1) return EINVAL;
+       self->canceldisable = new;
+       return 0;
+}
diff --git a/src/thread/pthread_setcanceltype.c b/src/thread/pthread_setcanceltype.c
new file mode 100644 (file)
index 0000000..c73db22
--- /dev/null
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int pthread_setcanceltype(int new, int *old)
+{
+       struct pthread *self = pthread_self();
+       if (old) *old = self->cancelasync;
+       if ((unsigned)new > 1) return EINVAL;
+       self->cancelasync = new;
+       return 0;
+}
diff --git a/src/thread/pthread_setspecific.c b/src/thread/pthread_setspecific.c
new file mode 100644 (file)
index 0000000..171cef4
--- /dev/null
@@ -0,0 +1,18 @@
+#include "pthread_impl.h"
+
+int pthread_setspecific(pthread_key_t k, const void *x)
+{
+       struct pthread *self = pthread_self();
+       /* Handle the case of the main thread */
+       if (!self->tsd) {
+               if (!x) return 0;
+               if (!(self->tsd = calloc(sizeof(void *), PTHREAD_KEYS_MAX)))
+                       return ENOMEM;
+       }
+       /* Avoid unnecessary COW */
+       if (self->tsd[k] != x) {
+               self->tsd[k] = (void *)x;
+               self->tsd_used = 1;
+       }
+       return 0;
+}
diff --git a/src/thread/pthread_spin_destroy.c b/src/thread/pthread_spin_destroy.c
new file mode 100644 (file)
index 0000000..e65a820
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_spin_destroy(pthread_spinlock_t *s)
+{
+       return 0;
+}
diff --git a/src/thread/pthread_spin_init.c b/src/thread/pthread_spin_init.c
new file mode 100644 (file)
index 0000000..681881c
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_spin_init(pthread_spinlock_t *s, int shared)
+{
+       return *s = 0;
+}
diff --git a/src/thread/pthread_spin_lock.c b/src/thread/pthread_spin_lock.c
new file mode 100644 (file)
index 0000000..59fa6ea
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_spin_lock(pthread_spinlock_t *s)
+{
+       while (a_xchg(s, 1));
+       return 0;
+}
diff --git a/src/thread/pthread_spin_trylock.c b/src/thread/pthread_spin_trylock.c
new file mode 100644 (file)
index 0000000..c12696b
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_spin_trylock(pthread_spinlock_t *s)
+{
+       return -a_xchg(s, 1) & EBUSY;
+}
diff --git a/src/thread/pthread_spin_unlock.c b/src/thread/pthread_spin_unlock.c
new file mode 100644 (file)
index 0000000..a7eab33
--- /dev/null
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_spin_unlock(pthread_spinlock_t *s)
+{
+       return *s = 0;
+}
diff --git a/src/thread/pthread_testcancel.c b/src/thread/pthread_testcancel.c
new file mode 100644 (file)
index 0000000..774b706
--- /dev/null
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+void pthread_testcancel()
+{
+       CANCELPT_BEGIN;
+       CANCELPT_END;
+}
diff --git a/src/time/__asctime.c b/src/time/__asctime.c
new file mode 100644 (file)
index 0000000..1853580
--- /dev/null
@@ -0,0 +1,27 @@
+#include <time.h>
+#include <stdio.h>
+#include <langinfo.h>
+
+const char *__langinfo(nl_item);
+
+char *__asctime(const struct tm *tm, char *buf)
+{
+       /* FIXME: change __langinfo to __C_langinfo once we have locales */
+       if (snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+               __langinfo(ABDAY_1+tm->tm_wday),
+               __langinfo(ABMON_1+tm->tm_mon),
+               tm->tm_mday, tm->tm_hour,
+               tm->tm_min, tm->tm_sec,
+               1900 + tm->tm_year) >= 26)
+       {
+               /* ISO C requires us to use the above format string,
+                * even if it will not fit in the buffer. Thus asctime_r
+                * is _supposed_ to crash if the fields in tm are too large.
+                * We follow this behavior and crash "gracefully" to warn
+                * application developers that they may not be so lucky
+                * on other implementations (e.g. stack smashing..).
+                */
+               *(int*)0 = 0;
+       }
+       return buf;
+}
diff --git a/src/time/__time.h b/src/time/__time.h
new file mode 100644 (file)
index 0000000..967e518
--- /dev/null
@@ -0,0 +1,9 @@
+time_t __tm_to_time(struct tm *);
+struct tm *__time_to_tm(time_t, struct tm *);
+void __tzset(void);
+struct tm *__dst_adjust(struct tm *tm);
+
+extern long __timezone;
+extern int __daylight;
+extern int __dst_offset;
+extern char *__tzname[2];
diff --git a/src/time/__time_to_tm.c b/src/time/__time_to_tm.c
new file mode 100644 (file)
index 0000000..a1ebc45
--- /dev/null
@@ -0,0 +1,81 @@
+#include <time.h>
+
+/* C defines the rounding for division in a nonsensical way */
+#define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
+
+#define DAYS_PER_400Y (365*400 + 97)
+#define DAYS_PER_100Y (365*100 + 24)
+#define DAYS_PER_4Y   (365*4   + 1)
+
+/* FIXME: use lldiv once it's fixed to compute quot,rem together */
+struct tm *__time_to_tm(time_t t, struct tm *tm)
+{
+       /* months are march-based */
+       static const int days_thru_month[] = {31,61,92,122,153,184,214,245,275,306,337,366};
+       long long bigday;
+       unsigned int day, year4, year100;
+       int year, year400;
+       int month;
+       int leap;
+       int hour, min, sec;
+       int wday, mday, yday;
+
+       /* start from 2000-03-01 (multiple of 400 years) */
+       t += -946684800 - 86400*(31+29);
+
+       bigday = Q(t, 86400);
+       sec = t-bigday*86400;
+
+       hour = sec/3600;
+       sec -= hour*3600;
+       min = sec/60;
+       sec -= min*60;
+
+       /* 2000-03-01 was a wednesday */
+       wday = (3+bigday)%7;
+       if (wday < 0) wday += 7;
+
+       t = -946684800LL - 86400*(31+29) + 9000000;
+       
+       year400 = Q(bigday, DAYS_PER_400Y);
+       day = bigday-year400*DAYS_PER_400Y;
+
+       year100 = day/DAYS_PER_100Y;
+       if (year100 == 4) year100--;
+       day -= year100*DAYS_PER_100Y;
+
+       year4 = day/DAYS_PER_4Y;
+       if (year4 == 25) year4--;
+       day -= year4*DAYS_PER_4Y;
+
+       year = day/365;
+       if (year == 4) year--;
+       day -= year*365;
+
+       leap = !year && (year4 || !year100);
+       yday = day + 31+28 + leap;
+       if (yday >= 365+leap) yday -= 365+leap;
+
+       year += 4*year4 + 100*year100 + 400*year400 + 2000-1900;
+
+       for (month=0; days_thru_month[month] <= day; month++);
+       if (month) day -= days_thru_month[month-1];
+       month += 2;
+       if (month >= 12) {
+               month -= 12;
+               year++;
+       }
+
+       mday = day+1;
+
+       tm->tm_sec = sec;
+       tm->tm_min = min;
+       tm->tm_hour= hour;
+       tm->tm_mday= mday;
+       tm->tm_mon = month;
+       tm->tm_year= year;
+       tm->tm_wday= wday;
+       tm->tm_yday= yday;
+
+       return tm;
+}
diff --git a/src/time/__tm_to_time.c b/src/time/__tm_to_time.c
new file mode 100644 (file)
index 0000000..3fa15fa
--- /dev/null
@@ -0,0 +1,33 @@
+#include <time.h>
+
+/* C defines the rounding for division in a nonsensical way */
+#define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
+
+time_t __tm_to_time(struct tm *tm)
+{
+       time_t year  = tm->tm_year + -100;
+       int    month = tm->tm_mon;
+       int    day   = tm->tm_mday;
+       int z4, z100, z400;
+
+       /* normalize month */
+       if (month >= 12) {
+               year += month/12;
+               month %= 12;
+       } else if (month < 0) {
+               year += month/12;
+               month %= 12;
+               if (month) {
+                       month += 12;
+                       year--;
+               }
+       }
+       z4 = Q(year - (month < 2), 4);
+       z100 = Q(z4, 25);
+       z400 = Q(z100, 4);
+       day += year*365 + z4 - z100 + z400 +
+               month[(int []){0,31,59,90,120,151,181,212,243,273,304,335}];
+       return (long long)day*86400
+               + tm->tm_hour*3600 + tm->tm_min*60 + tm->tm_sec
+               - -946684800; /* the dawn of time :) */
+}
diff --git a/src/time/asctime.c b/src/time/asctime.c
new file mode 100644 (file)
index 0000000..3102eb8
--- /dev/null
@@ -0,0 +1,9 @@
+#include <time.h>
+
+char *__asctime(const struct tm *, char *);
+
+char *asctime(const struct tm *tm)
+{
+       static char buf[26];
+       return __asctime(tm, buf);
+}
diff --git a/src/time/asctime_r.c b/src/time/asctime_r.c
new file mode 100644 (file)
index 0000000..e51b880
--- /dev/null
@@ -0,0 +1,8 @@
+#include <time.h>
+
+char *__asctime(const struct tm *, char *);
+
+char *asctime_r(const struct tm *tm, char *buf)
+{
+       return __asctime(tm, buf);
+}
diff --git a/src/time/clock.c b/src/time/clock.c
new file mode 100644 (file)
index 0000000..2feddb3
--- /dev/null
@@ -0,0 +1,9 @@
+#include <time.h>
+#include <sys/times.h>
+
+/* this function assumes 100 hz linux and corrects for it */
+clock_t clock()
+{
+       struct tms tms;
+       return (unsigned long)times(&tms)*10000;
+}
diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c
new file mode 100644 (file)
index 0000000..dab09d5
--- /dev/null
@@ -0,0 +1,7 @@
+#include <time.h>
+#include "syscall.h"
+
+int clock_gettime(clockid_t clk, struct timespec *ts)
+{
+       return syscall2(__NR_clock_gettime, clk, (long)ts);
+}
diff --git a/src/time/ctime.c b/src/time/ctime.c
new file mode 100644 (file)
index 0000000..185ec55
--- /dev/null
@@ -0,0 +1,6 @@
+#include <time.h>
+
+char *ctime(const time_t *t)
+{
+       return asctime(localtime(t));
+}
diff --git a/src/time/ctime_r.c b/src/time/ctime_r.c
new file mode 100644 (file)
index 0000000..d2260a1
--- /dev/null
@@ -0,0 +1,8 @@
+#include <time.h>
+
+char *ctime_r(const time_t *t, char *buf)
+{
+       struct tm tm;
+       localtime_r(t, &tm);
+       return asctime_r(&tm, buf);
+}
diff --git a/src/time/difftime.c b/src/time/difftime.c
new file mode 100644 (file)
index 0000000..80a18cc
--- /dev/null
@@ -0,0 +1,6 @@
+#include <time.h>
+
+double difftime(time_t t1, time_t t0)
+{
+       return t1-t0;
+}
diff --git a/src/time/gettimeofday.c b/src/time/gettimeofday.c
new file mode 100644 (file)
index 0000000..2b8a287
--- /dev/null
@@ -0,0 +1,9 @@
+#define SYSCALL_RETURN_ERRNO
+#include <sys/time.h>
+#include "syscall.h"
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+       syscall2(__NR_gettimeofday, (long)tv, 0);
+       return 0;
+}
diff --git a/src/time/gmtime.c b/src/time/gmtime.c
new file mode 100644 (file)
index 0000000..d4d5d1f
--- /dev/null
@@ -0,0 +1,11 @@
+#include <time.h>
+
+#include "__time.h"
+
+struct tm *gmtime(const time_t *t)
+{
+       static struct tm tm;
+       __time_to_tm(*t, &tm);
+       tm.tm_isdst = 0;
+       return &tm;
+}
diff --git a/src/time/gmtime_r.c b/src/time/gmtime_r.c
new file mode 100644 (file)
index 0000000..5b565a6
--- /dev/null
@@ -0,0 +1,10 @@
+#include <time.h>
+
+#include "__time.h"
+
+struct tm *gmtime_r(const time_t *t, struct tm *result)
+{
+       __time_to_tm(*t, result);
+       result->tm_isdst = 0;
+       return result;
+}
diff --git a/src/time/localtime.c b/src/time/localtime.c
new file mode 100644 (file)
index 0000000..abd5e84
--- /dev/null
@@ -0,0 +1,12 @@
+#include <time.h>
+
+#include "__time.h"
+
+struct tm *localtime(const time_t *t)
+{
+       static struct tm tm;
+       __tzset();
+       __time_to_tm(*t - __timezone, &tm);
+       tm.tm_isdst = -1;
+       return __dst_adjust(&tm);
+}
diff --git a/src/time/localtime_r.c b/src/time/localtime_r.c
new file mode 100644 (file)
index 0000000..2bf1037
--- /dev/null
@@ -0,0 +1,11 @@
+#include <time.h>
+
+#include "__time.h"
+
+struct tm *localtime_r(const time_t *t, struct tm *result)
+{
+       __tzset();
+       __time_to_tm(*t - __timezone, result);
+       result->tm_isdst = -1;
+       return __dst_adjust(result);
+}
diff --git a/src/time/mktime.c b/src/time/mktime.c
new file mode 100644 (file)
index 0000000..858cd50
--- /dev/null
@@ -0,0 +1,24 @@
+#include <time.h>
+
+#include "__time.h"
+
+time_t mktime(struct tm *tm)
+{
+       int isdst = tm->tm_isdst;
+       time_t t, lt;
+
+       __tzset();
+
+       tm->tm_sec += __timezone;
+       if (isdst > 0) tm->tm_sec += __dst_offset;
+
+       t = __tm_to_time(tm);
+       
+       lt = t - __timezone;
+       if (isdst > 0) lt -= __dst_offset;
+       __time_to_tm(lt, tm);
+
+       __dst_adjust(tm);
+       
+       return t;
+}
diff --git a/src/time/nanosleep.c b/src/time/nanosleep.c
new file mode 100644 (file)
index 0000000..5ac4c35
--- /dev/null
@@ -0,0 +1,13 @@
+#include <unistd.h>
+#include <time.h>
+#include "syscall.h"
+#include "libc.h"
+
+int nanosleep(const struct timespec *req, struct timespec *rem)
+{
+       int ret;
+       CANCELPT_BEGIN;
+       ret = syscall2(__NR_nanosleep, (long)req, (long)rem);
+       CANCELPT_END;
+       return ret;
+}
diff --git a/src/time/strftime.c b/src/time/strftime.c
new file mode 100644 (file)
index 0000000..f1b9463
--- /dev/null
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <langinfo.h>
+#include <time.h>
+#include "__time.h"
+
+// FIXME: integer overflows
+
+const char *__langinfo(nl_item);
+
+size_t strftime(char *s, size_t n, const char *f, const struct tm *tm)
+{
+       nl_item item;
+       int val;
+       const char *fmt;
+       size_t l;
+       for (l=0; *f && l<n; f++) {
+               if (*f == '%') {
+do_fmt:
+               switch (*++f) {
+               case '%':
+                       goto literal;
+               case 'E':
+               case 'O':
+                       goto do_fmt;
+               case 'a':
+                       item = ABDAY_1 + tm->tm_wday;
+                       goto nl_strcat;
+               case 'A':
+                       item = DAY_1 + tm->tm_wday;
+                       goto nl_strcat;
+               case 'h':
+               case 'b':
+                       item = ABMON_1 + tm->tm_mon;
+                       goto nl_strcat;
+               case 'B':
+                       item = MON_1 + tm->tm_mon;
+                       goto nl_strcat;
+               case 'c':
+                       item = D_T_FMT;
+                       goto nl_strftime;
+               case 'C':
+                       val = (1900+tm->tm_year) / 100;
+                       fmt = "%02d";
+                       goto number;
+               case 'd':
+                       val = tm->tm_mday;
+                       fmt = "%02d";
+                       goto number;
+               case 'D':
+                       fmt = "%m/%d/%y";
+                       goto recu_strftime;
+               case 'e':
+                       val = tm->tm_mday;
+                       fmt = "%2d";
+                       goto number;
+               case 'F':
+                       fmt = "%Y-%m-%d";
+                       goto recu_strftime;
+               case 'g':
+                       // FIXME
+                       val = 0; //week_based_year(tm)%100;
+                       fmt = "%02d";
+                       goto number;
+               case 'G':
+                       // FIXME
+                       val = 0; //week_based_year(tm);
+                       fmt = "%04d";
+                       goto number;
+               case 'H':
+                       val = tm->tm_hour;
+                       fmt = "%02d";
+                       goto number;
+               case 'I':
+                       val = tm->tm_hour;
+                       if (!val) val = 12;
+                       else if (val > 12) val -= 12;
+                       fmt = "%02d";
+                       goto number;
+               case 'j':
+                       val = tm->tm_yday+1;
+                       fmt = "%03d";
+                       goto number;
+               case 'm':
+                       val = tm->tm_mon+1;
+                       fmt = "%02d";
+                       goto number;
+               case 'M':
+                       val = tm->tm_min;
+                       fmt = "%02d";
+                       goto number;
+               case 'n':
+                       s[l++] = '\n';
+                       continue;
+               case 'p':
+                       item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
+                       goto nl_strcat;
+               case 'r':
+                       item = T_FMT_AMPM;
+                       goto nl_strftime;
+               case 'R':
+                       fmt = "%H:%M";
+                       goto recu_strftime;
+               case 'S':
+                       val = tm->tm_sec;
+                       fmt = "%02d";
+                       goto number;
+               case 't':
+                       s[l++] = '\t';
+                       continue;
+               case 'T':
+                       fmt = "%H:%M:%S";
+                       goto recu_strftime;
+               case 'u':
+                       val = tm->tm_wday ? tm->tm_wday : 7;
+                       fmt = "%d";
+                       goto number;
+               case 'U':
+               case 'V':
+               case 'W':
+                       // FIXME: week number mess..
+                       continue;
+               case 'w':
+                       val = tm->tm_wday;
+                       fmt = "%d";
+                       goto number;
+               case 'x':
+                       item = D_FMT;
+                       goto nl_strftime;
+               case 'X':
+                       item = T_FMT;
+                       goto nl_strftime;
+               case 'y':
+                       val = tm->tm_year % 100;
+                       fmt = "%02d";
+                       goto number;
+               case 'Y':
+                       val = tm->tm_year + 1900;
+                       fmt = "%04d";
+                       goto number;
+               case 'z':
+                       if (tm->tm_isdst < 0) continue;
+                       val = -__timezone - (tm->tm_isdst ? __dst_offset : 0);
+                       l += snprintf(s+l, n-l, "%+.2d%.2d", val/3600, abs(val%3600)/60);
+                       continue;
+               case 'Z':
+                       if (tm->tm_isdst < 0 || !__tzname[0] || !__tzname[0][0])
+                               continue;
+                       l += snprintf(s+l, n-l, "%s", __tzname[!!tm->tm_isdst]);
+                       continue;
+               default:
+                       return 0;
+               }
+               }
+literal:
+               s[l++] = *f;
+               continue;
+number:
+               l += snprintf(s+l, n-l, fmt, val);
+               continue;
+nl_strcat:
+               l += snprintf(s+l, n-l, "%s", __langinfo(item));
+               continue;
+nl_strftime:
+               fmt = __langinfo(item);
+recu_strftime:
+               l += strftime(s+l, n-l, fmt, tm);
+       }
+       if (l >= n) return 0;
+       s[l] = 0;
+       return l;
+}
diff --git a/src/time/strptime.c b/src/time/strptime.c
new file mode 100644 (file)
index 0000000..db72e61
--- /dev/null
@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <langinfo.h>
+#include <time.h>
+
+const char *__langinfo(nl_item);
+
+char *strptime(const char *s, const char *f, struct tm *tm)
+{
+       return NULL;
+}
+
+#if 0
+
+char *strptime(const char *s, const char *f, struct tm *tm)
+{
+       nl_item item;
+       int *dest;
+       const char *fmt;
+       for (; *f; f++) {
+               if (isspace(*f)) goto whitespace;
+               if (*f == '%') {
+do_fmt:
+               switch (*++f) {
+               case '%':
+                       goto literal;
+               case 'E':
+               case 'O':
+                       goto do_fmt;
+               case 'a':
+                       item = ABDAY_1 + tm->tm_wday;
+                       goto nl_strcat;
+               case 'A':
+                       item = DAY_1 + tm->tm_wday;
+                       goto nl_strcat;
+               case 'h':
+               case 'b':
+                       item = ABMON_1 + tm->tm_mon;
+                       goto nl_strcat;
+               case 'B':
+                       item = MON_1 + tm->tm_mon;
+                       goto nl_strcat;
+               case 'c':
+                       item = D_T_FMT;
+                       goto nl_strftime;
+               case 'C':
+                       val = (1900+tm->tm_year) / 100;
+                       fmt = "%02d";
+                       goto number;
+               case 'd':
+                       val = tm->tm_mday;
+                       fmt = "%02d";
+                       goto number;
+               case 'D':
+                       fmt = "%m/%d/%y";
+                       goto recu_strftime;
+               case 'e':
+                       val = tm->tm_mday;
+                       fmt = "%2d";
+                       goto number;
+               case 'F':
+                       fmt = "%Y-%m-%d";
+                       goto recu_strftime;
+               case 'g':
+                       // FIXME
+                       val = 0; //week_based_year(tm)%100;
+                       fmt = "%02d";
+                       goto number;
+               case 'G':
+                       // FIXME
+                       val = 0; //week_based_year(tm);
+                       fmt = "%04d";
+                       goto number;
+               case 'H':
+                       val = tm->tm_hour;
+                       fmt = "%02d";
+                       goto number;
+               case 'I':
+                       val = tm->tm_hour;
+                       if (!val) val = 12;
+                       else if (val > 12) val -= 12;
+                       fmt = "%02d";
+                       goto number;
+               case 'j':
+                       val = tm->tm_yday+1;
+                       fmt = "%03d";
+                       goto number;
+               case 'm':
+                       val = tm->tm_mon+1;
+                       fmt = "%02d";
+                       goto number;
+               case 'M':
+                       val = tm->tm_min;
+                       fmt = "%02d";
+                       goto number;
+               case 'n':
+               case 't':
+                       goto whitespace;
+               case 'p':
+                       item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
+                       goto nl_strcat;
+               case 'r':
+                       item = T_FMT_AMPM;
+                       goto nl_strftime;
+               case 'R':
+                       fmt = "%H:%M";
+                       goto recu_strftime;
+               case 'S':
+                       val = tm->tm_sec;
+                       fmt = "%02d";
+                       goto number;
+               case 'T':
+                       fmt = "%H:%M:%S";
+                       goto recu_strftime;
+               case 'u':
+                       val = tm->tm_wday ? tm->tm_wday : 7;
+                       fmt = "%d";
+                       goto number;
+               case 'U':
+               case 'V':
+               case 'W':
+                       // FIXME: week number mess..
+                       continue;
+               case 'w':
+                       val = tm->tm_wday;
+                       fmt = "%d";
+                       goto number;
+               case 'x':
+                       item = D_FMT;
+                       goto nl_strftime;
+               case 'X':
+                       item = T_FMT;
+                       goto nl_strftime;
+               case 'y':
+                       val = tm->tm_year % 100;
+                       fmt = "%02d";
+                       goto number;
+               case 'Y':
+                       val = tm->tm_year + 1900;
+                       fmt = "%04d";
+                       goto number;
+               case 'z':
+                       if (tm->tm_isdst < 0) continue;
+                       val = timezone + (tm->tm_isdst) ? __dst_offset : 0;
+                       l += snprintf(s+l, n-l, "%+02d%02d", val/60, abs(val%60));
+                       continue;
+               case 'Z':
+                       if (tm->tm_isdst < 0 || !tzname[0] || !tzname[0][0])
+                               continue;
+                       l += snprintf(s+l, n-l, "%s", tzname[!!tm->tm_isdst]);
+                       continue;
+               }
+               default:
+                       return NULL;
+               }
+literal:
+               if (*s++ != *f) return NULL;
+               continue;
+whitespace:
+               while(isspace(*s)) s++;
+               continue;
+number:
+               l += snprintf(s+l, n-l, fmt, val);
+               continue;
+nl_strcat:
+               l += snprintf(s+l, n-l, "%s", __langinfo(item));
+               continue;
+nl_strftime:
+               fmt = __langinfo(item);
+recu_strftime:
+               l += strftime(s+l, n-l, fmt, tm);
+       }
+       if (l >= n) return 0;
+       s[l] = 0;
+       return l;
+}
+
+#endif
diff --git a/src/time/time.c b/src/time/time.c
new file mode 100644 (file)
index 0000000..3457dad
--- /dev/null
@@ -0,0 +1,12 @@
+#define SYSCALL_RETURN_ERRNO
+#include <time.h>
+#include <sys/time.h>
+#include "syscall.h"
+
+time_t time(time_t *t)
+{
+       struct timeval tv;
+       syscall2(__NR_gettimeofday, (long)&tv, 0);
+       if (t) *t = tv.tv_sec;
+       return tv.tv_sec;
+}
diff --git a/src/time/times.c b/src/time/times.c
new file mode 100644 (file)
index 0000000..e9b5a82
--- /dev/null
@@ -0,0 +1,7 @@
+#include <sys/times.h>
+#include "syscall.h"
+
+clock_t times(struct tms *tms)
+{
+       return syscall1(__NR_times, (long)&tms);
+}
diff --git a/src/time/timezone.s b/src/time/timezone.s
new file mode 100644 (file)
index 0000000..4e167b0
--- /dev/null
@@ -0,0 +1,27 @@
+.data
+
+.global timezone
+.global __timezone
+.global daylight
+.global __daylight
+.global tzname
+.global __tzname
+
+__timezone:
+timezone:
+       .long 0
+.size timezone,.-timezone
+.size __timezone,.-__timezone
+
+__daylight:
+daylight:
+       .long 0
+.size daylight,.-daylight
+.size __daylight,.-__daylight
+
+__tzname:
+tzname:
+       .long 0
+       .long 0
+.size tzname,.-tzname
+.size __tzname,.-__tzname
diff --git a/src/time/tzset.c b/src/time/tzset.c
new file mode 100644 (file)
index 0000000..6d69957
--- /dev/null
@@ -0,0 +1,173 @@
+#include <time.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include "libc.h"
+
+#include "__time.h"
+
+long  __timezone = 0;
+int   __daylight = 0;
+char *__tzname[2] = { 0, 0 };
+int   __dst_offset = 0;
+
+weak_alias(__timezone, timezone);
+weak_alias(__daylight, daylight);
+weak_alias(__tzname, tzname);
+weak_alias(__dst_offset, dst_offset);
+
+static char std_name[TZNAME_MAX+1];
+static char dst_name[TZNAME_MAX+1];
+
+/* all elements are zero-based */
+static struct rule {
+       char month;
+       char week;
+       short day;
+       int time;
+} __dst_start, __dst_end;
+
+static void zname(char *d, char **s)
+{
+       int i;
+       for (i=0; i<TZNAME_MAX && isalpha(d[i]=**s); i++, (*s)++);
+       d[i] = 0;
+}
+
+static int hhmmss(char **s)
+{
+       int ofs = strtol(*s, s, 10)*3600;
+       if (ofs >= 0) {
+               if (**s == ':') ofs += strtol(*s+1, s, 10)*60;
+               if (**s == ':') ofs += strtol(*s+1, s, 10);
+       } else {
+               if (**s == ':') ofs -= strtol(*s+1, s, 10)*60;
+               if (**s == ':') ofs -= strtol(*s+1, s, 10);
+       }
+       return ofs;
+}
+
+static int dstrule(struct rule *rule, char **s)
+{
+       if (**s != ',') return -1;
+       switch (*++*s) {
+       case 'J':
+               rule->month = 'J';
+               rule->day = strtol(*s+1, s, 10)-1;
+               break;
+       case 'M':
+               rule->month = strtol(*s+1, s, 10)-1;
+               if (**s != '.' || rule->month < 0 || rule->month > 11)
+                       return -1;
+               rule->week = strtol(*s+1, s, 10)-1;
+               if (**s != '.' || rule->week < 0 || rule->week > 4)
+                       return -1;
+               rule->day = strtol(*s+1, s, 10);
+               if (rule->day < 0 || rule->day > 6)
+                       return -1;
+               break;
+       default:
+               rule->month = 'L';
+               rule->day = strtol(*s+1, s, 10);
+               break;
+       }
+       if (**s == '/') {
+               (*s)++;
+               rule->time = hhmmss(s);
+       } else rule->time = 7200;
+       return 0;
+}
+
+void tzset(void)
+{
+       char *z, *a;
+       
+       strcpy(std_name, "GMT");
+       strcpy(dst_name, "GMT");
+       __tzname[0] = std_name;
+       __tzname[1] = dst_name;
+       __timezone = 0;
+       __daylight = 0;
+       
+       if (!(z = getenv("TZ")) || !isalpha(*z)) return;
+
+       zname(std_name, &z);
+       __timezone = hhmmss(&z);
+
+       zname(dst_name, &z);
+       if (dst_name[0]) __daylight=1;
+       a = z;
+       __dst_offset = hhmmss(&z) - __timezone;
+       if (z==a) __dst_offset = -3600;
+
+       if (dstrule(&__dst_start, &z) || dstrule(&__dst_end, &z))
+               __daylight = 0;
+}
+
+void __tzset(void)
+{
+       static int lock, init;
+       if (init) return;
+       LOCK(&lock);
+       if (!init) tzset();
+       init=1;
+       UNLOCK(&lock);
+}
+
+static int is_leap(int year)
+{
+       year -= 100;
+       return !(year&3) && ((year%100) || !(year%400));
+}
+
+static int cutoff_yday(struct tm *tm, struct rule *rule)
+{
+       static const char days_in_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+       static const int first_day[] = {0,31,59,90,120,151,181,212,243,273,304,335};
+       int yday, mday, leap;
+       
+       switch (rule->month) {
+       case 'J':
+               return rule->day + (tm->tm_mon > 1 && is_leap(tm->tm_year));
+       case 'L':
+               return rule->day;
+       default:
+               yday = first_day[rule->month];
+               leap = is_leap(tm->tm_year);
+               if (rule->month > 1 && leap) yday++;
+               mday = (rule->day - (yday + tm->tm_wday - tm->tm_yday) + 1400)%7 + 7*rule->week;
+               if (mday >= days_in_month[rule->month] + (leap && rule->month == 1))
+                       mday -= 7;
+               return mday + yday;
+       }
+}
+
+struct tm *__dst_adjust(struct tm *tm)
+{
+       time_t t;
+       int start, end, secs;
+       int after_start, before_end;
+
+       if (tm->tm_isdst >= 0) return tm;
+       if (!__daylight) {
+               tm->tm_isdst = 0;
+               return tm;
+       }
+       
+       secs = tm->tm_hour*3600 + tm->tm_min*60 + tm->tm_sec;
+       start = cutoff_yday(tm, &__dst_start);
+       end = cutoff_yday(tm, &__dst_end);
+
+       after_start = (tm->tm_yday > start || (tm->tm_yday == start && secs >= __dst_start.time));
+       before_end = (tm->tm_yday < end || (tm->tm_yday == end && secs < __dst_end.time));
+
+       if ((after_start && before_end) || ((end < start) && (after_start || before_end))) {
+               tm->tm_sec -= __dst_offset;
+               tm->tm_isdst = 1;
+               t = __tm_to_time(tm);
+               return __time_to_tm(t, tm);
+       } else tm->tm_isdst = 0;
+
+       return tm;
+}
diff --git a/src/time/utime.c b/src/time/utime.c
new file mode 100644 (file)
index 0000000..56e9e13
--- /dev/null
@@ -0,0 +1,12 @@
+#include <utime.h>
+#include "syscall.h"
+
+int utime(const char *path, const struct utimbuf *times)
+{
+       long ktimes[2];
+       if (times) {
+               ktimes[0] = times->actime;
+               ktimes[1] = times->modtime;
+       }
+       return syscall2(__NR_utime, (long)path, times ? (long)ktimes : 0);
+}
diff --git a/src/unistd/_exit.c b/src/unistd/_exit.c
new file mode 100644 (file)
index 0000000..d2e84c4
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+void _exit(int status)
+{
+       _Exit(status);
+}
diff --git a/src/unistd/access.c b/src/unistd/access.c
new file mode 100644 (file)
index 0000000..2c10e58
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int access(const char *filename, int amode)
+{
+       return syscall2(__NR_access, (long)filename, amode);
+}
diff --git a/src/unistd/alarm.c b/src/unistd/alarm.c
new file mode 100644 (file)
index 0000000..bba444d
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+unsigned alarm(unsigned seconds)
+{
+       return syscall1(__NR_alarm, seconds);
+}
diff --git a/src/unistd/chdir.c b/src/unistd/chdir.c
new file mode 100644 (file)
index 0000000..c89bda3
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int chdir(const char *path)
+{
+       return syscall1(__NR_chdir, (long)path);
+}
diff --git a/src/unistd/chown.c b/src/unistd/chown.c
new file mode 100644 (file)
index 0000000..6069a2f
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int chown(const char *path, uid_t uid, gid_t gid)
+{
+       return syscall3(__NR_chown32, (long)path, uid, gid);
+}
diff --git a/src/unistd/close.c b/src/unistd/close.c
new file mode 100644 (file)
index 0000000..97302f6
--- /dev/null
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int close(int fd)
+{
+       int ret = __syscall_close(fd);
+       CANCELPT_BEGIN;
+       CANCELPT_END;
+       return ret;
+}
diff --git a/src/unistd/confstr.c b/src/unistd/confstr.c
new file mode 100644 (file)
index 0000000..4332f72
--- /dev/null
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+size_t confstr(int name, char *buf, size_t len)
+{
+       const char *s = "";
+       if (!name) {
+               s = "/bin:/usr/bin";
+       } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>31U) {
+               errno = EINVAL;
+               return 0;
+       }
+       // snprintf is overkill but avoid wasting code size to implement
+       // this completely useless function and its truncation semantics
+       return snprintf(buf, len, "%s", s);
+}
diff --git a/src/unistd/ctermid.c b/src/unistd/ctermid.c
new file mode 100644 (file)
index 0000000..21b44ec
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+
+char *ctermid(char *s)
+{
+       static char *s2;
+       int fd;
+       if (!s) {
+               if (!s2) s2 = malloc(L_ctermid);
+               s = s2;
+       }
+       fd = open("/dev/tty", O_WRONLY | O_NOCTTY);
+       if (fd < 0)
+               return strcpy(s, "");
+       if (ttyname_r(fd, s, L_ctermid))
+               strcpy(s, "");
+       close(fd);
+       return s;
+}
diff --git a/src/unistd/dup.c b/src/unistd/dup.c
new file mode 100644 (file)
index 0000000..b11cd71
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int dup(int fd)
+{
+       return syscall1(__NR_dup, fd);
+}
diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c
new file mode 100644 (file)
index 0000000..9332544
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int dup2(int old, int new)
+{
+       return __syscall_dup2(old, new);
+}
diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c
new file mode 100644 (file)
index 0000000..99a9378
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int faccessat(int fd, const char *filename, int amode, int flag)
+{
+       return syscall4(__NR_faccessat, fd, (long)filename, amode, flag);
+}
diff --git a/src/unistd/fchdir.c b/src/unistd/fchdir.c
new file mode 100644 (file)
index 0000000..b2acbc2
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int fchdir(int fd)
+{
+       return syscall1(__NR_fchdir, fd);
+}
diff --git a/src/unistd/fchown.c b/src/unistd/fchown.c
new file mode 100644 (file)
index 0000000..990f006
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int fchown(int fd, uid_t uid, gid_t gid)
+{
+       return syscall3(__NR_fchown32, fd, uid, gid);
+}
diff --git a/src/unistd/fchownat.c b/src/unistd/fchownat.c
new file mode 100644 (file)
index 0000000..7062642
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flag)
+{
+       return syscall5(__NR_fchownat, fd, (long)path, uid, gid, flag);
+}
diff --git a/src/unistd/fdatasync.c b/src/unistd/fdatasync.c
new file mode 100644 (file)
index 0000000..ef7c9a9
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int fdatasync(int fd)
+{
+       return 0;
+}
diff --git a/src/unistd/fsync.c b/src/unistd/fsync.c
new file mode 100644 (file)
index 0000000..7cfedc9
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int fsync(int fd)
+{
+       //return syscall1(__NR_fsync, fd);
+       return 0;
+}
diff --git a/src/unistd/ftruncate.c b/src/unistd/ftruncate.c
new file mode 100644 (file)
index 0000000..e0b2f4b
--- /dev/null
@@ -0,0 +1,15 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int ftruncate(int fd, off_t length)
+{
+       if (sizeof(long) == 8)
+               return syscall2(__NR_ftruncate, fd, length);
+       else {
+               union { long long ll; long l[2]; } u = { length };
+               return syscall3(__NR_ftruncate64, fd, u.l[0], u.l[1]);
+       }
+}
+
+LFS64(ftruncate);
diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c
new file mode 100644 (file)
index 0000000..4910f42
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <errno.h>
+#include "syscall.h"
+
+char *getcwd(char *buf, size_t size)
+{
+       return syscall2(__NR_getcwd, (long)buf, size) < 0 ? NULL : buf;
+}
diff --git a/src/unistd/getegid.c b/src/unistd/getegid.c
new file mode 100644 (file)
index 0000000..0e626b7
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+gid_t getegid(void)
+{
+       return syscall0(__NR_getegid32);
+}
diff --git a/src/unistd/geteuid.c b/src/unistd/geteuid.c
new file mode 100644 (file)
index 0000000..39d6ac7
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+uid_t geteuid(void)
+{
+       return syscall0(__NR_geteuid32);
+}
diff --git a/src/unistd/getgid.c b/src/unistd/getgid.c
new file mode 100644 (file)
index 0000000..186635a
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+gid_t getgid(void)
+{
+       return syscall0(__NR_getgid32);
+}
diff --git a/src/unistd/getgroups.c b/src/unistd/getgroups.c
new file mode 100644 (file)
index 0000000..6f19870
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int getgroups(int count, gid_t list[])
+{
+       /* this depends on our gid_t being 32bit */
+       return syscall2(__NR_getgroups32, count, (long)list);
+}
diff --git a/src/unistd/gethostname.c b/src/unistd/gethostname.c
new file mode 100644 (file)
index 0000000..a406c4e
--- /dev/null
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <string.h>
+
+int gethostname(char *name, size_t len)
+{
+       size_t i;
+       struct utsname uts;
+       if (uname(&uts)) return -1;
+       if (len > sizeof uts.nodename) len = sizeof uts.nodename;
+       for (i=0; i<len && (name[i] = uts.nodename[i]); i++);
+       if (i==len) name[i-1] = 0;
+       return 0;
+}
diff --git a/src/unistd/getlogin.c b/src/unistd/getlogin.c
new file mode 100644 (file)
index 0000000..0601191
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+char *getlogin(void)
+{
+       return getenv("LOGNAME");
+}
diff --git a/src/unistd/getlogin_r.c b/src/unistd/getlogin_r.c
new file mode 100644 (file)
index 0000000..f04f71e
--- /dev/null
@@ -0,0 +1,13 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+int getlogin_r(char *name, size_t size)
+{
+       char *logname = getlogin();
+       if (!logname) return ENXIO; /* or...? */
+       if (strlen(name) >= size) return ERANGE;
+       strcpy(name, logname);
+       return 0;
+}
diff --git a/src/unistd/getpgid.c b/src/unistd/getpgid.c
new file mode 100644 (file)
index 0000000..50d716b
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t getpgid(pid_t pid)
+{
+       return syscall1(__NR_getpgid, pid);
+}
diff --git a/src/unistd/getpgrp.c b/src/unistd/getpgrp.c
new file mode 100644 (file)
index 0000000..2004630
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t getpgrp(void)
+{
+       return syscall0(__NR_getpgrp);
+}
diff --git a/src/unistd/getpid.c b/src/unistd/getpid.c
new file mode 100644 (file)
index 0000000..31cbe1c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t getpid(void)
+{
+       return syscall0(__NR_getpid);
+}
diff --git a/src/unistd/getppid.c b/src/unistd/getppid.c
new file mode 100644 (file)
index 0000000..a324182
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t getppid(void)
+{
+       return syscall0(__NR_getppid);
+}
diff --git a/src/unistd/getsid.c b/src/unistd/getsid.c
new file mode 100644 (file)
index 0000000..064229c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t getsid(pid_t pid)
+{
+       return syscall1(__NR_getsid, pid);
+}
diff --git a/src/unistd/getuid.c b/src/unistd/getuid.c
new file mode 100644 (file)
index 0000000..9d4e53f
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+uid_t getuid(void)
+{
+       return syscall0(__NR_getuid32);
+}
diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c
new file mode 100644 (file)
index 0000000..cff6e9f
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <termios.h>
+
+int isatty(int fd)
+{
+       struct termios t;
+       return tcgetattr(fd, &t) == 0;
+}
diff --git a/src/unistd/lchown.c b/src/unistd/lchown.c
new file mode 100644 (file)
index 0000000..30e8391
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int lchown(const char *path, uid_t uid, gid_t gid)
+{
+       return syscall3(__NR_lchown32, (long)path, uid, gid);
+}
diff --git a/src/unistd/link.c b/src/unistd/link.c
new file mode 100644 (file)
index 0000000..f121bb9
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int link(const char *existing, const char *new)
+{
+       return syscall2(__NR_link, (long)existing, (long)new);
+}
diff --git a/src/unistd/linkat.c b/src/unistd/linkat.c
new file mode 100644 (file)
index 0000000..0eb5122
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int linkat(int fd1, const char *existing, int fd2, const char *new, int flag)
+{
+       return syscall5(__NR_linkat, fd1, (long)existing, fd2, (long)new, flag);
+}
diff --git a/src/unistd/lseek.c b/src/unistd/lseek.c
new file mode 100644 (file)
index 0000000..0dab267
--- /dev/null
@@ -0,0 +1,16 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+       /* optimized away at compiletime */
+       if (sizeof(long) == 8)
+               return syscall3(__NR_lseek, fd, offset, whence);
+       else {
+               off_t result;
+               return syscall5(__NR__llseek, fd, offset>>32, offset, (long)&result, whence) ? -1 : result;
+       }
+}
+
+LFS64(lseek);
diff --git a/src/unistd/nice.c b/src/unistd/nice.c
new file mode 100644 (file)
index 0000000..4b28ef4
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int nice(int inc)
+{
+       return syscall1(__NR_nice, inc);
+}
diff --git a/src/unistd/pause.c b/src/unistd/pause.c
new file mode 100644 (file)
index 0000000..1472065
--- /dev/null
@@ -0,0 +1,12 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int pause(void)
+{
+       int r;
+       CANCELPT_BEGIN;
+       r = syscall0(__NR_pause);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/unistd/pipe.c b/src/unistd/pipe.c
new file mode 100644 (file)
index 0000000..2dfc9c9
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int pipe(int fd[2])
+{
+       return syscall1(__NR_pipe, (long)fd);
+}
diff --git a/src/unistd/pread.c b/src/unistd/pread.c
new file mode 100644 (file)
index 0000000..029ba3d
--- /dev/null
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
+{
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall5(__NR_pread64, fd, (long)buf, size, SYSCALL_LL(ofs));
+       CANCELPT_END;
+       return r;
+}
+
+LFS64(pread);
diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c
new file mode 100644 (file)
index 0000000..8f23d1b
--- /dev/null
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
+{
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall5(__NR_pwrite64, fd, (long)buf, size, SYSCALL_LL(ofs));
+       CANCELPT_END;
+       return r;
+}
+
+LFS64(pwrite);
diff --git a/src/unistd/read.c b/src/unistd/read.c
new file mode 100644 (file)
index 0000000..87ff1f1
--- /dev/null
@@ -0,0 +1,12 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t read(int fd, void *buf, size_t count)
+{
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = __syscall_read(fd, buf, count);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/unistd/readlink.c b/src/unistd/readlink.c
new file mode 100644 (file)
index 0000000..f6b1635
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int readlink(const char *path, char *buf, size_t bufsize)
+{
+       return syscall3(__NR_readlink, (long)path, (long)buf, bufsize);
+}
diff --git a/src/unistd/readlinkat.c b/src/unistd/readlinkat.c
new file mode 100644 (file)
index 0000000..8171050
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int readlinkat(int fd, const char *path, char *buf, size_t bufsize)
+{
+       return syscall4(__NR_readlinkat, fd, (long)path, (long)buf, bufsize);
+}
diff --git a/src/unistd/readv.c b/src/unistd/readv.c
new file mode 100644 (file)
index 0000000..e311f9d
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/uio.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t readv(int fd, const struct iovec *iov, int count)
+{
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall3(__NR_readv, fd, (long)iov, count);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/unistd/renameat.c b/src/unistd/renameat.c
new file mode 100644 (file)
index 0000000..0dae9f1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "syscall.h"
+
+int renameat(int oldfd, const char *old, int newfd, const char *new)
+{
+       return syscall4(__NR_renameat, oldfd, (long)old, newfd, (long)new);
+}
diff --git a/src/unistd/rmdir.c b/src/unistd/rmdir.c
new file mode 100644 (file)
index 0000000..8e18c7a
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int rmdir(const char *path)
+{
+       return syscall1(__NR_rmdir, (long)path);
+}
diff --git a/src/unistd/setegid.c b/src/unistd/setegid.c
new file mode 100644 (file)
index 0000000..8534884
--- /dev/null
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+int setegid(gid_t egid)
+{
+       return setregid(-1, egid);
+}
diff --git a/src/unistd/seteuid.c b/src/unistd/seteuid.c
new file mode 100644 (file)
index 0000000..0aaa86e
--- /dev/null
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+int seteuid(uid_t euid)
+{
+       return setreuid(-1, euid);
+}
diff --git a/src/unistd/setgid.c b/src/unistd/setgid.c
new file mode 100644 (file)
index 0000000..00c7a03
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int setgid(gid_t gid)
+{
+       if (libc.rsyscall) return libc.rsyscall(__NR_setgid32, gid, 0, 0, 0, 0, 0);
+       return syscall1(__NR_setgid32, gid);
+}
diff --git a/src/unistd/setpgid.c b/src/unistd/setpgid.c
new file mode 100644 (file)
index 0000000..748d290
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t setpgid(pid_t pid, pid_t pgid)
+{
+       return syscall2(__NR_setpgid, pid, pgid);
+}
diff --git a/src/unistd/setpgrp.c b/src/unistd/setpgrp.c
new file mode 100644 (file)
index 0000000..a2a37f6
--- /dev/null
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+pid_t setpgrp(void)
+{
+       return setpgid(0, 0);
+}
diff --git a/src/unistd/setregid.c b/src/unistd/setregid.c
new file mode 100644 (file)
index 0000000..d25dab7
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int setregid(gid_t rgid, gid_t egid)
+{
+       if (libc.rsyscall) return libc.rsyscall(__NR_setregid32, rgid, egid, 0, 0, 0, 0);
+       return syscall2(__NR_setregid32, rgid, egid);
+}
diff --git a/src/unistd/setreuid.c b/src/unistd/setreuid.c
new file mode 100644 (file)
index 0000000..0ba2277
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int setreuid(uid_t ruid, uid_t euid)
+{
+       if (libc.rsyscall) return libc.rsyscall(__NR_setreuid32, ruid, euid, 0, 0, 0, 0);
+       return syscall2(__NR_setreuid32, ruid, euid);
+}
diff --git a/src/unistd/setsid.c b/src/unistd/setsid.c
new file mode 100644 (file)
index 0000000..e2c5690
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+pid_t setsid(void)
+{
+       return syscall0(__NR_setsid);
+}
diff --git a/src/unistd/setuid.c b/src/unistd/setuid.c
new file mode 100644 (file)
index 0000000..53b74d8
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int setuid(uid_t uid)
+{
+       if (libc.rsyscall) return libc.rsyscall(__NR_setuid32, uid, 0, 0, 0, 0, 0);
+       return syscall1(__NR_setuid32, uid);
+}
diff --git a/src/unistd/sleep.c b/src/unistd/sleep.c
new file mode 100644 (file)
index 0000000..d645094
--- /dev/null
@@ -0,0 +1,10 @@
+#include <unistd.h>
+#include <time.h>
+
+unsigned sleep(unsigned seconds)
+{
+       struct timespec tv = { .tv_sec = seconds, .tv_nsec = 0 };
+       if (nanosleep(&tv, &tv))
+               return tv.tv_sec;
+       return 0;
+}
diff --git a/src/unistd/symlink.c b/src/unistd/symlink.c
new file mode 100644 (file)
index 0000000..8d380d8
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int symlink(const char *existing, const char *new)
+{
+       return syscall2(__NR_symlink, (long)existing, (long)new);
+}
diff --git a/src/unistd/symlinkat.c b/src/unistd/symlinkat.c
new file mode 100644 (file)
index 0000000..9693b22
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int symlinkat(const char *existing, int fd, const char *new)
+{
+       return syscall3(__NR_symlinkat, (long)existing, fd, (long)new);
+}
diff --git a/src/unistd/sync.c b/src/unistd/sync.c
new file mode 100644 (file)
index 0000000..a49808f
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+void sync(void)
+{
+       syscall0(__NR_sync);
+}
diff --git a/src/unistd/tcgetpgrp.c b/src/unistd/tcgetpgrp.c
new file mode 100644 (file)
index 0000000..50080c7
--- /dev/null
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+pid_t tcgetpgrp(int fd)
+{
+       int pgrp;
+       if (ioctl(fd, TIOCGPGRP, &pgrp) < 0)
+               return -1;
+       return pgrp;
+}
diff --git a/src/unistd/tcsetpgrp.c b/src/unistd/tcsetpgrp.c
new file mode 100644 (file)
index 0000000..67c38cb
--- /dev/null
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int tcsetpgrp(int fd, pid_t pgrp)
+{
+       int pgrp_int = pgrp;
+       return ioctl(fd, TIOCSPGRP, &pgrp_int);
+}
diff --git a/src/unistd/truncate.c b/src/unistd/truncate.c
new file mode 100644 (file)
index 0000000..f75e824
--- /dev/null
@@ -0,0 +1,15 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+int truncate(const char *path, off_t length)
+{
+       if (sizeof(long) == 8)
+               return syscall2(__NR_truncate, (long)path, length);
+       else {
+               union { long long ll; long l[2]; } u = { length };
+               return syscall3(__NR_truncate64, (long)path, u.l[0], u.l[1]);
+       }
+}
+
+LFS64(truncate);
diff --git a/src/unistd/ttyname.c b/src/unistd/ttyname.c
new file mode 100644 (file)
index 0000000..0f3e114
--- /dev/null
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+char *ttyname(int fd)
+{
+       static char buf[TTY_NAME_MAX];
+       int result;
+       if ((result = ttyname_r(fd, buf, sizeof buf))) {
+               errno = result;
+               return NULL;
+       }
+       return buf;
+}
diff --git a/src/unistd/ttyname_r.c b/src/unistd/ttyname_r.c
new file mode 100644 (file)
index 0000000..f86fbd9
--- /dev/null
@@ -0,0 +1,19 @@
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+int ttyname_r(int fd, char *name, size_t size)
+{
+       char procname[sizeof "/proc/self/fd/" + 3*sizeof(int) + 2];
+       ssize_t l;
+
+       if (!isatty(fd)) return ENOTTY;
+
+       snprintf(procname, sizeof procname, "/proc/self/fd/%d", fd);
+       l = readlink(procname, name, size);
+
+       if (l < 0) return errno;
+       else if (l == size) return ERANGE;
+       else return 0;
+}
diff --git a/src/unistd/ualarm.c b/src/unistd/ualarm.c
new file mode 100644 (file)
index 0000000..be85303
--- /dev/null
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "syscall.h"
+
+/* FIXME: ?? */
+useconds_t ualarm(useconds_t useconds, useconds_t interval)
+{
+       return -1;
+}
diff --git a/src/unistd/unlink.c b/src/unistd/unlink.c
new file mode 100644 (file)
index 0000000..fb57792
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int unlink(const char *path)
+{
+       return __syscall_unlink(path);
+}
diff --git a/src/unistd/unlinkat.c b/src/unistd/unlinkat.c
new file mode 100644 (file)
index 0000000..47fccc1
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "syscall.h"
+
+int unlinkat(int fd, const char *path, int flag)
+{
+       return syscall3(__NR_unlinkat, fd, (long)path, flag);
+}
diff --git a/src/unistd/usleep.c b/src/unistd/usleep.c
new file mode 100644 (file)
index 0000000..e386901
--- /dev/null
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <time.h>
+
+int usleep(useconds_t useconds)
+{
+       struct timespec tv = {
+               .tv_sec = useconds/1000000,
+               .tv_nsec = (useconds%1000000)*1000
+       };
+       return nanosleep(&tv, &tv);
+}
diff --git a/src/unistd/write.c b/src/unistd/write.c
new file mode 100644 (file)
index 0000000..426cfc5
--- /dev/null
@@ -0,0 +1,12 @@
+#include <unistd.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+       int r;
+       CANCELPT_BEGIN;
+       r = __syscall_write(fd, buf, count);
+       CANCELPT_END;
+       return r;
+}
diff --git a/src/unistd/writev.c b/src/unistd/writev.c
new file mode 100644 (file)
index 0000000..a6a118a
--- /dev/null
@@ -0,0 +1,12 @@
+#include <sys/uio.h>
+#include "syscall.h"
+#include "libc.h"
+
+ssize_t writev(int fd, const struct iovec *iov, int count)
+{
+       ssize_t r;
+       CANCELPT_BEGIN;
+       r = syscall3(__NR_writev, fd, (long)iov, count);
+       CANCELPT_END;
+       return r;
+}
diff --git a/tools/gen-musl-gcc.sh b/tools/gen-musl-gcc.sh
new file mode 100644 (file)
index 0000000..89f7f4d
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+printf '#!/bin/sh\n\nlibc_prefix="%s"\n' "$1"
+
+cat <<"EOF"
+libc_lib=$libc_prefix/lib
+libc_inc=$libc_prefix/include
+libc_crt="$libc_lib/crt1.o"
+libc_start="$libc_lib/crti.o"
+libc_end="$libc_lib/crtn.o"
+
+gcc_inc=$libc_inc
+libgcc="`gcc \"$@\" -print-file-name=libgcc.a`"
+
+gcc -wrapper sh,-c,'
+x= ; y= ; z= ; s= ; for i ; do
+  [ "$z" ] || set -- ; z=1
+  case "$i" in
+    -shared) s=1 ; set -- "$@" -shared ;;
+    -Lxxxxxx) x=1 ;;
+    -xxxxxx) x= ; [ "$s" ] || set -- "$@" "'"$libc_start"'" "'"$libc_crt"'" ;;
+    -l*) [ "$y" ] || set -- "$@" '"$libc_end"' ; set -- "$@" "$i" ; y=1 ;;
+    *) [ "$x" ] || set -- "$@" "$i" ;;
+  esac
+done
+exec "$0" "$@"
+' -std=gnu99 -nostdinc -nostdlib \
+  -isystem "$libc_inc" -isystem "$gcc_inc" \
+  -Wl,-xxxxxx "$@" -L"$libc_lib" -lc "$libgcc" -Lxxxxxx -Wl,-nostdlib
+EOF