summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING504
-rw-r--r--COPYRIGHT31
-rw-r--r--INSTALL61
-rw-r--r--Makefile97
-rw-r--r--README44
-rw-r--r--crt/crt1.c0
-rw-r--r--crt/crti.c0
-rw-r--r--crt/crtn.c0
-rw-r--r--crt/i386/crt1.s17
-rw-r--r--dist/config.mak25
-rw-r--r--include/alloca.h9
-rw-r--r--include/arpa/inet.h33
-rw-r--r--include/arpa/nameser.h465
-rw-r--r--include/arpa/telnet.h251
-rw-r--r--include/assert.h17
-rwxr-xr-xinclude/bits/alltypes.h.sh115
-rw-r--r--include/bits/endian.h1
-rw-r--r--include/bits/errno.h125
-rw-r--r--include/bits/fcntl.h59
-rw-r--r--include/bits/fenv.h34
-rw-r--r--include/bits/float.h11
-rw-r--r--include/bits/in.h89
-rw-r--r--include/bits/ioctl.h182
-rw-r--r--include/bits/ipc.h22
-rw-r--r--include/bits/limits.h32
-rw-r--r--include/bits/mman.h39
-rw-r--r--include/bits/posix.h2
-rw-r--r--include/bits/pthread.h6
-rw-r--r--include/bits/reg.h19
-rw-r--r--include/bits/setjmp.h1
-rw-r--r--include/bits/shm.h18
-rw-r--r--include/bits/signal.h98
-rw-r--r--include/bits/socket.h189
-rw-r--r--include/bits/stat.h25
-rw-r--r--include/bits/statfs.h16
-rw-r--r--include/bits/stdint.h23
-rw-r--r--include/bits/stdio.h10
-rw-r--r--include/bits/sysmacros.h7
-rw-r--r--include/bits/tcp.h1
-rw-r--r--include/bits/termios.h158
-rw-r--r--include/bits/uio.h4
-rw-r--r--include/bits/user.h77
-rw-r--r--include/bits/wait.h11
-rw-r--r--include/bits/wexitstatus.h9
-rw-r--r--include/byteswap.h0
-rw-r--r--include/cpio.h29
-rw-r--r--include/ctype.h53
-rw-r--r--include/dirent.h41
-rw-r--r--include/dlfcn.h19
-rw-r--r--include/elf.h2524
-rw-r--r--include/endian.h17
-rw-r--r--include/errno.h18
-rw-r--r--include/fcntl.h43
-rw-r--r--include/features.h1
-rw-r--r--include/fenv.h28
-rw-r--r--include/float.h34
-rw-r--r--include/fnmatch.h25
-rw-r--r--include/ftw.h31
-rw-r--r--include/getopt.h33
-rw-r--r--include/glob.h41
-rw-r--r--include/grp.h35
-rw-r--r--include/iconv.h22
-rw-r--r--include/inttypes.h227
-rw-r--r--include/langinfo.h85
-rw-r--r--include/libgen.h15
-rw-r--r--include/libintl.h25
-rw-r--r--include/limits.h101
-rw-r--r--include/linux/loop.h69
-rw-r--r--include/linux/version.h2
-rw-r--r--include/locale.h84
-rw-r--r--include/malloc.h0
-rw-r--r--include/math.h300
-rw-r--r--include/mntent.h43
-rw-r--r--include/net/ethernet.h47
-rw-r--r--include/net/if.h122
-rw-r--r--include/net/if_arp.h133
-rw-r--r--include/net/route.h116
-rw-r--r--include/netdb.h148
-rw-r--r--include/netinet/icmp6.h305
-rw-r--r--include/netinet/if_ether.h108
-rw-r--r--include/netinet/in.h158
-rw-r--r--include/netinet/ip.h186
-rw-r--r--include/netinet/ip6.h142
-rw-r--r--include/netinet/ip_icmp.h192
-rw-r--r--include/netinet/tcp.h6
-rw-r--r--include/netinet/udp.h35
-rw-r--r--include/nl_types.h24
-rw-r--r--include/paths.h40
-rw-r--r--include/poll.h35
-rw-r--r--include/pthread.h216
-rw-r--r--include/pty.h17
-rw-r--r--include/pwd.h38
-rw-r--r--include/regex.h59
-rw-r--r--include/resolv.h143
-rw-r--r--include/sched.h37
-rw-r--r--include/search.h6
-rw-r--r--include/semaphore.h27
-rw-r--r--include/setjmp.h30
-rw-r--r--include/shadow.h44
-rw-r--r--include/signal.h98
-rw-r--r--include/stdarg.h32
-rw-r--r--include/stdbool.h13
-rw-r--r--include/stddef.h19
-rw-r--r--include/stdint.h107
-rw-r--r--include/stdio.h144
-rw-r--r--include/stdlib.h129
-rw-r--r--include/string.h72
-rw-r--r--include/strings.h36
-rw-r--r--include/stropts.h16
-rw-r--r--include/sys/epoll.h61
-rw-r--r--include/sys/file.h21
-rw-r--r--include/sys/ioctl.h14
-rw-r--r--include/sys/ipc.h23
-rw-r--r--include/sys/kd.h8
-rw-r--r--include/sys/klog.h14
-rw-r--r--include/sys/mman.h37
-rw-r--r--include/sys/mount.h28
-rw-r--r--include/sys/msg.h36
-rw-r--r--include/sys/param.h15
-rw-r--r--include/sys/poll.h1
-rw-r--r--include/sys/prctl.h64
-rw-r--r--include/sys/procfs.h81
-rw-r--r--include/sys/ptrace.h77
-rw-r--r--include/sys/reboot.h18
-rw-r--r--include/sys/reg.h9
-rw-r--r--include/sys/resource.h74
-rw-r--r--include/sys/select.h34
-rw-r--r--include/sys/sem.h69
-rw-r--r--include/sys/shm.h18
-rw-r--r--include/sys/signalfd.h40
-rw-r--r--include/sys/socket.h64
-rw-r--r--include/sys/soundcard.h1
-rw-r--r--include/sys/stat.h90
-rw-r--r--include/sys/statfs.h10
-rw-r--r--include/sys/statvfs.h30
-rw-r--r--include/sys/stropts.h1
-rw-r--r--include/sys/swap.h11
-rw-r--r--include/sys/sysctl.h9
-rw-r--r--include/sys/sysinfo.h29
-rw-r--r--include/sys/sysmacros.h6
-rw-r--r--include/sys/time.h49
-rw-r--r--include/sys/times.h17
-rw-r--r--include/sys/types.h56
-rw-r--r--include/sys/ucontext.h1
-rw-r--r--include/sys/uio.h14
-rw-r--r--include/sys/un.h13
-rw-r--r--include/sys/user.h15
-rw-r--r--include/sys/utsname.h21
-rw-r--r--include/sys/vfs.h1
-rw-r--r--include/sys/vt.h1
-rw-r--r--include/sys/wait.h28
-rw-r--r--include/syslog.h54
-rw-r--r--include/tar.h33
-rw-r--r--include/termios.h39
-rw-r--r--include/time.h113
-rw-r--r--include/ucontext.h38
-rw-r--r--include/ulimit.h17
-rw-r--r--include/unistd.h464
-rw-r--r--include/utime.h24
-rw-r--r--include/utmp.h23
-rw-r--r--include/utmpx.h52
-rw-r--r--include/wchar.h152
-rw-r--r--include/wctype.h44
-rw-r--r--include/wordexp.h40
-rw-r--r--src/conf/fpathconf.c35
-rw-r--r--src/conf/pathconf.c6
-rw-r--r--src/conf/sysconf.c222
-rw-r--r--src/ctype/__ctype_get_mb_cur_max.c6
-rw-r--r--src/ctype/isalnum.c6
-rw-r--r--src/ctype/isalpha.c7
-rw-r--r--src/ctype/isascii.c6
-rw-r--r--src/ctype/isblank.c6
-rw-r--r--src/ctype/iscntrl.c6
-rw-r--r--src/ctype/isdigit.c7
-rw-r--r--src/ctype/isgraph.c4
-rw-r--r--src/ctype/islower.c7
-rw-r--r--src/ctype/isprint.c4
-rw-r--r--src/ctype/ispunct.c6
-rw-r--r--src/ctype/isspace.c6
-rw-r--r--src/ctype/isupper.c7
-rw-r--r--src/ctype/iswalnum.c9
-rw-r--r--src/ctype/iswalpha.c6
-rw-r--r--src/ctype/iswblank.c8
-rw-r--r--src/ctype/iswcntrl.c10
-rw-r--r--src/ctype/iswctype.c63
-rw-r--r--src/ctype/iswdigit.c9
-rw-r--r--src/ctype/iswgraph.c7
-rw-r--r--src/ctype/iswlower.c6
-rw-r--r--src/ctype/iswprint.c10
-rw-r--r--src/ctype/iswpunct.c138
-rw-r--r--src/ctype/iswspace.c15
-rw-r--r--src/ctype/iswupper.c6
-rw-r--r--src/ctype/iswxdigit.c7
-rw-r--r--src/ctype/isxdigit.c6
-rw-r--r--src/ctype/toascii.c7
-rw-r--r--src/ctype/tolower.c7
-rw-r--r--src/ctype/toupper.c7
-rw-r--r--src/ctype/towctrans.c246
-rw-r--r--src/ctype/wcswidth.c8
-rw-r--r--src/ctype/wctrans.c16
-rw-r--r--src/ctype/wcwidth.c185
-rw-r--r--src/dirent/__dirent.h9
-rw-r--r--src/dirent/__getdents.c12
-rw-r--r--src/dirent/alphasort.c10
-rw-r--r--src/dirent/closedir.c11
-rw-r--r--src/dirent/dirfd.c7
-rw-r--r--src/dirent/fdopendir.c26
-rw-r--r--src/dirent/opendir.c25
-rw-r--r--src/dirent/readdir.c32
-rw-r--r--src/dirent/readdir_r.c30
-rw-r--r--src/dirent/rewinddir.c13
-rw-r--r--src/dirent/scandir.c50
-rw-r--r--src/dirent/seekdir.c12
-rw-r--r--src/dirent/telldir.c7
-rw-r--r--src/env/__environ.c7
-rw-r--r--src/env/__libc_start_main.c26
-rw-r--r--src/env/clearenv.c9
-rw-r--r--src/env/getenv.c14
-rw-r--r--src/env/putenv.c59
-rw-r--r--src/env/setenv.c31
-rw-r--r--src/env/unsetenv.c32
-rw-r--r--src/errno/__errno_location.c11
-rw-r--r--src/errno/__strerror.h101
-rw-r--r--src/errno/strerror.c22
-rw-r--r--src/exit/_Exit.c9
-rw-r--r--src/exit/abort.c8
-rw-r--r--src/exit/assert.c9
-rw-r--r--src/exit/atexit.c57
-rw-r--r--src/exit/exit.c28
-rw-r--r--src/fcntl/creat.c9
-rw-r--r--src/fcntl/fcntl.c22
-rw-r--r--src/fcntl/open.c21
-rw-r--r--src/fcntl/openat.c21
-rw-r--r--src/internal/atomic.h110
-rw-r--r--src/internal/clone.h22
-rw-r--r--src/internal/futex.h16
-rw-r--r--src/internal/libc.c3
-rw-r--r--src/internal/libc.h43
-rw-r--r--src/internal/locale_impl.h5
-rw-r--r--src/internal/pthread_impl.h68
-rw-r--r--src/internal/stdio_impl.h100
-rw-r--r--src/internal/syscall.c11
-rw-r--r--src/internal/syscall.h469
-rw-r--r--src/internal/util.h5
-rw-r--r--src/ipc/ftok.c10
-rw-r--r--src/ipc/ipc.h13
-rw-r--r--src/ipc/semctl.c18
-rw-r--r--src/ipc/semget.c12
-rw-r--r--src/ipc/semop.c12
-rw-r--r--src/ipc/shmat.c17
-rw-r--r--src/ipc/shmctl.c12
-rw-r--r--src/ipc/shmdt.c12
-rw-r--r--src/ipc/shmget.c12
-rw-r--r--src/linux/brk.c6
-rw-r--r--src/linux/chroot.c8
-rw-r--r--src/linux/daemon.c31
-rw-r--r--src/linux/epoll_create.c7
-rw-r--r--src/linux/epoll_create1.c7
-rw-r--r--src/linux/epoll_ctl.c7
-rw-r--r--src/linux/epoll_pwait.c7
-rw-r--r--src/linux/epoll_wait.c7
-rw-r--r--src/linux/getdtablesize.c9
-rw-r--r--src/linux/gethostid.c4
-rw-r--r--src/linux/getopt_long.c52
-rw-r--r--src/linux/getpagesize.c7
-rw-r--r--src/linux/getpass.c39
-rw-r--r--src/linux/initgroups.c15
-rw-r--r--src/linux/klogctl.c7
-rw-r--r--src/linux/mntent.c57
-rw-r--r--src/linux/mount.c8
-rw-r--r--src/linux/prctl.c13
-rw-r--r--src/linux/reboot.c8
-rw-r--r--src/linux/sbrk.c7
-rw-r--r--src/linux/sendfile.c10
-rw-r--r--src/linux/setgroups.c9
-rw-r--r--src/linux/sethostname.c8
-rw-r--r--src/linux/settimeofday.c7
-rw-r--r--src/linux/signalfd.c7
-rw-r--r--src/linux/stime.c7
-rw-r--r--src/linux/swapoff.c8
-rw-r--r--src/linux/swapon.c8
-rw-r--r--src/linux/sysinfo.c9
-rw-r--r--src/linux/umount.c8
-rw-r--r--src/linux/umount2.c8
-rw-r--r--src/linux/utimes.c13
-rw-r--r--src/linux/wait3.c11
-rw-r--r--src/linux/wait4.c19
-rw-r--r--src/locale/catclose.c6
-rw-r--r--src/locale/catgets.c6
-rw-r--r--src/locale/catopen.c6
-rw-r--r--src/locale/duplocale.c11
-rw-r--r--src/locale/freelocale.c7
-rw-r--r--src/locale/iconv.c568
-rw-r--r--src/locale/intl.c67
-rw-r--r--src/locale/isalnum_l.c6
-rw-r--r--src/locale/isalpha_l.c6
-rw-r--r--src/locale/isblank_l.c6
-rw-r--r--src/locale/iscntrl_l.c6
-rw-r--r--src/locale/isdigit_l.c6
-rw-r--r--src/locale/isgraph_l.c6
-rw-r--r--src/locale/islower_l.c6
-rw-r--r--src/locale/isprint_l.c6
-rw-r--r--src/locale/ispunct_l.c6
-rw-r--r--src/locale/isspace_l.c6
-rw-r--r--src/locale/isupper_l.c6
-rw-r--r--src/locale/isxdigit_l.c6
-rw-r--r--src/locale/langinfo.c58
-rw-r--r--src/locale/localeconv.c22
-rw-r--r--src/locale/newlocale.c11
-rw-r--r--src/locale/nl_langinfo.c13
-rw-r--r--src/locale/setlocale.c9
-rw-r--r--src/locale/strcoll.c6
-rw-r--r--src/locale/strxfrm.c9
-rw-r--r--src/locale/tmp390
-rw-r--r--src/locale/tolower_l.c6
-rw-r--r--src/locale/toupper_l.c6
-rw-r--r--src/locale/wcscoll.c7
-rw-r--r--src/locale/wcsxfrm.c12
-rw-r--r--src/malloc/DESIGN22
-rw-r--r--src/malloc/__brk.c7
-rw-r--r--src/malloc/__simple_malloc.c44
-rw-r--r--src/malloc/calloc.c23
-rw-r--r--src/malloc/malloc.c515
-rw-r--r--src/malloc/memalign.c13
-rw-r--r--src/malloc/posix_memalign.c47
-rw-r--r--src/math/__fpclassify.c14
-rw-r--r--src/math/__fpclassifyf.c14
-rw-r--r--src/math/__fpclassifyl.c16
-rw-r--r--src/math/e_acos.c99
-rw-r--r--src/math/e_acosf.c77
-rw-r--r--src/math/e_acosh.c59
-rw-r--r--src/math/e_acoshf.c45
-rw-r--r--src/math/e_asin.c109
-rw-r--r--src/math/e_asinf.c80
-rw-r--r--src/math/e_atan2.c120
-rw-r--r--src/math/e_atan2f.c93
-rw-r--r--src/math/e_atanh.c59
-rw-r--r--src/math/e_atanhf.c42
-rw-r--r--src/math/e_cosh.c82
-rw-r--r--src/math/e_coshf.c59
-rw-r--r--src/math/e_exp.c155
-rw-r--r--src/math/e_expf.c91
-rw-r--r--src/math/e_fmod.c129
-rw-r--r--src/math/e_fmodf.c101
-rw-r--r--src/math/e_hypot.c121
-rw-r--r--src/math/e_hypotf.c79
-rw-r--r--src/math/e_log.c131
-rw-r--r--src/math/e_log10.c83
-rw-r--r--src/math/e_log10f.c51
-rw-r--r--src/math/e_logf.c81
-rw-r--r--src/math/e_pow.c300
-rw-r--r--src/math/e_powf.c243
-rw-r--r--src/math/e_rem_pio2.c163
-rw-r--r--src/math/e_rem_pio2f.c175
-rw-r--r--src/math/e_remainder.c69
-rw-r--r--src/math/e_remainderf.c61
-rw-r--r--src/math/e_scalb.c35
-rw-r--r--src/math/e_scalbf.c31
-rw-r--r--src/math/e_sinh.c75
-rw-r--r--src/math/e_sinhf.c56
-rw-r--r--src/math/e_sqrt.c442
-rw-r--r--src/math/e_sqrtf.c85
-rw-r--r--src/math/i386/e_exp.s36
-rw-r--r--src/math/i386/e_expf.s1
-rw-r--r--src/math/i386/e_log.s6
-rw-r--r--src/math/i386/e_log10.s6
-rw-r--r--src/math/i386/e_log10f.s6
-rw-r--r--src/math/i386/e_logf.s6
-rw-r--r--src/math/i386/e_remainder.s16
-rw-r--r--src/math/i386/e_remainderf.s0
-rw-r--r--src/math/i386/e_sqrt.s4
-rw-r--r--src/math/i386/e_sqrtf.s4
-rw-r--r--src/math/i386/s_ceil.s0
-rw-r--r--src/math/i386/s_ceilf.s0
-rw-r--r--src/math/i386/s_fabs.s5
-rw-r--r--src/math/i386/s_fabsf.s5
-rw-r--r--src/math/i386/s_floor.s0
-rw-r--r--src/math/i386/s_floorf.s0
-rw-r--r--src/math/i386/s_ldexp.s0
-rw-r--r--src/math/i386/s_ldexpf.s0
-rw-r--r--src/math/i386/s_rint.s5
-rw-r--r--src/math/i386/s_rintf.s5
-rw-r--r--src/math/i386/s_scalbln.s11
-rw-r--r--src/math/i386/s_scalblnf.s11
-rw-r--r--src/math/i386/s_trunc.s36
-rw-r--r--src/math/i386/s_truncf.s0
-rw-r--r--src/math/k_cos.c85
-rw-r--r--src/math/k_cosf.c52
-rw-r--r--src/math/k_rem_pio2.c300
-rw-r--r--src/math/k_rem_pio2f.c192
-rw-r--r--src/math/k_sin.c68
-rw-r--r--src/math/k_sinf.c42
-rw-r--r--src/math/k_tan.c149
-rw-r--r--src/math/k_tanf.c105
-rw-r--r--src/math/math_private.h143
-rw-r--r--src/math/s_asinh.c53
-rw-r--r--src/math/s_asinhf.c45
-rw-r--r--src/math/s_atan.c115
-rw-r--r--src/math/s_atanf.c95
-rw-r--r--src/math/s_cbrt.c77
-rw-r--r--src/math/s_cbrtf.c67
-rw-r--r--src/math/s_ceil.c68
-rw-r--r--src/math/s_ceilf.c49
-rw-r--r--src/math/s_copysign.c30
-rw-r--r--src/math/s_copysignf.c33
-rw-r--r--src/math/s_cos.c74
-rw-r--r--src/math/s_cosf.c47
-rw-r--r--src/math/s_erf.c298
-rw-r--r--src/math/s_erff.c207
-rw-r--r--src/math/s_expm1.c217
-rw-r--r--src/math/s_expm1f.c122
-rw-r--r--src/math/s_fabs.c27
-rw-r--r--src/math/s_fabsf.c30
-rw-r--r--src/math/s_floor.c69
-rw-r--r--src/math/s_floorf.c58
-rw-r--r--src/math/s_ilogb.c45
-rw-r--r--src/math/s_ilogbf.c37
-rw-r--r--src/math/s_ldexp.c6
-rw-r--r--src/math/s_ldexpf.c6
-rw-r--r--src/math/s_llrint.c8
-rw-r--r--src/math/s_log1p.c157
-rw-r--r--src/math/s_log1pf.c96
-rw-r--r--src/math/s_logb.c34
-rw-r--r--src/math/s_logbf.c31
-rw-r--r--src/math/s_lrint.c8
-rw-r--r--src/math/s_lrintf.c8
-rw-r--r--src/math/s_modf.c71
-rw-r--r--src/math/s_modff.c52
-rw-r--r--src/math/s_nextafter.c72
-rw-r--r--src/math/s_nextafterf.c63
-rw-r--r--src/math/s_remquo.c149
-rw-r--r--src/math/s_remquof.c118
-rw-r--r--src/math/s_rint.c80
-rw-r--r--src/math/s_rintf.c45
-rw-r--r--src/math/s_round.c48
-rw-r--r--src/math/s_roundf.c48
-rw-r--r--src/math/s_scalbln.c61
-rw-r--r--src/math/s_scalblnf.c57
-rw-r--r--src/math/s_sin.c74
-rw-r--r--src/math/s_sinf.c45
-rw-r--r--src/math/s_tan.c68
-rw-r--r--src/math/s_tanf.c40
-rw-r--r--src/math/s_tanh.c74
-rw-r--r--src/math/s_tanhf.c52
-rw-r--r--src/math/s_trunc.c58
-rw-r--r--src/math/s_truncf.c50
-rw-r--r--src/misc/basename.c12
-rw-r--r--src/misc/bswap_32.c7
-rw-r--r--src/misc/bswap_64.c9
-rw-r--r--src/misc/crypt.c2578
-rw-r--r--src/misc/cuserid.c13
-rw-r--r--src/misc/dirname.c15
-rw-r--r--src/misc/ffs.c9
-rw-r--r--src/misc/ftw.c9
-rw-r--r--src/misc/getdomainname.c9
-rw-r--r--src/misc/getgrouplist.c11
-rw-r--r--src/misc/getopt.c63
-rw-r--r--src/misc/getpriority.c9
-rw-r--r--src/misc/getrlimit.c15
-rw-r--r--src/misc/getrusage.c20
-rw-r--r--src/misc/getsubopt.c23
-rw-r--r--src/misc/ioctl.c13
-rw-r--r--src/misc/lockf.c33
-rw-r--r--src/misc/nftw.c121
-rw-r--r--src/misc/openpty.c33
-rw-r--r--src/misc/pty.c35
-rw-r--r--src/misc/realpath.c6
-rw-r--r--src/misc/sched_yield.c10
-rw-r--r--src/misc/setpriority.c7
-rw-r--r--src/misc/setrlimit.c11
-rw-r--r--src/misc/syslog.c115
-rw-r--r--src/misc/uname.c8
-rw-r--r--src/mman/madvise.c10
-rw-r--r--src/mman/mlock.c7
-rw-r--r--src/mman/mlockall.c7
-rw-r--r--src/mman/mmap.c18
-rw-r--r--src/mman/mprotect.c7
-rw-r--r--src/mman/mremap.c19
-rw-r--r--src/mman/msync.c8
-rw-r--r--src/mman/munlock.c7
-rw-r--r--src/mman/munlockall.c7
-rw-r--r--src/mman/munmap.c11
-rw-r--r--src/mman/posix_madvise.c6
-rw-r--r--src/multibyte/btowc.c7
-rw-r--r--src/multibyte/decode.c47
-rw-r--r--src/multibyte/internal.c60
-rw-r--r--src/multibyte/internal.h61
-rw-r--r--src/multibyte/mblen.c17
-rw-r--r--src/multibyte/mbrlen.c18
-rw-r--r--src/multibyte/mbrtowc.c58
-rw-r--r--src/multibyte/mbsinit.c17
-rw-r--r--src/multibyte/mbsnrtowcs.c61
-rw-r--r--src/multibyte/mbsrtowcs.c121
-rw-r--r--src/multibyte/mbstowcs.c18
-rw-r--r--src/multibyte/mbtowc.c19
-rw-r--r--src/multibyte/wcrtomb.c38
-rw-r--r--src/multibyte/wcsnrtombs.c51
-rw-r--r--src/multibyte/wcsrtombs.c58
-rw-r--r--src/multibyte/wcstombs.c17
-rw-r--r--src/multibyte/wctob.c8
-rw-r--r--src/multibyte/wctomb.c18
-rw-r--r--src/network/__dns.c267
-rw-r--r--src/network/__dns.h14
-rw-r--r--src/network/__ipparse.c40
-rw-r--r--src/network/accept.c14
-rw-r--r--src/network/bind.c9
-rw-r--r--src/network/connect.c14
-rw-r--r--src/network/dn_expand.c28
-rw-r--r--src/network/ent.c26
-rw-r--r--src/network/freeaddrinfo.c7
-rw-r--r--src/network/gai_strerror.c21
-rw-r--r--src/network/getaddrinfo.c224
-rw-r--r--src/network/gethostbyaddr.c15
-rw-r--r--src/network/gethostbyaddr_r.c71
-rw-r--r--src/network/gethostbyname.c63
-rw-r--r--src/network/gethostbyname2.c16
-rw-r--r--src/network/gethostbyname2_r.c99
-rw-r--r--src/network/gethostbyname_r.c11
-rw-r--r--src/network/getnameinfo.c54
-rw-r--r--src/network/getpeername.c9
-rw-r--r--src/network/getservbyname.c12
-rw-r--r--src/network/getservbyname_r.c41
-rw-r--r--src/network/getservbyport.c12
-rw-r--r--src/network/getservbyport_r.c43
-rw-r--r--src/network/getsockname.c9
-rw-r--r--src/network/getsockopt.c13
-rw-r--r--src/network/h_errno.c1
-rw-r--r--src/network/hstrerror.c16
-rw-r--r--src/network/htonl.c10
-rw-r--r--src/network/htons.c10
-rw-r--r--src/network/in6addr_any.c3
-rw-r--r--src/network/in6addr_loopback.c3
-rw-r--r--src/network/inet_addr.c11
-rw-r--r--src/network/inet_aton.c7
-rw-r--r--src/network/inet_ntoa.c10
-rw-r--r--src/network/inet_ntop.c48
-rw-r--r--src/network/inet_pton.c31
-rw-r--r--src/network/listen.c9
-rw-r--r--src/network/ntohl.c10
-rw-r--r--src/network/ntohs.c10
-rw-r--r--src/network/proto.c58
-rw-r--r--src/network/recv.c14
-rw-r--r--src/network/recvfrom.c17
-rw-r--r--src/network/recvmsg.c14
-rw-r--r--src/network/res_init.c4
-rw-r--r--src/network/res_query.c20
-rw-r--r--src/network/send.c14
-rw-r--r--src/network/sendmsg.c14
-rw-r--r--src/network/sendto.c17
-rw-r--r--src/network/serv.c16
-rw-r--r--src/network/setsockopt.c9
-rw-r--r--src/network/shutdown.c9
-rw-r--r--src/network/sockatmark.c11
-rw-r--r--src/network/socket.c9
-rw-r--r--src/network/socketcall.h24
-rw-r--r--src/network/socketpair.c9
-rw-r--r--src/passwd/getgr_r.c53
-rw-r--r--src/passwd/getgrent.c39
-rw-r--r--src/passwd/getgrent_a.c46
-rw-r--r--src/passwd/getpw_r.c46
-rw-r--r--src/passwd/getpwent.c39
-rw-r--r--src/passwd/getpwent_a.c37
-rw-r--r--src/passwd/getspent.c14
-rw-r--r--src/passwd/getspnam.c17
-rw-r--r--src/passwd/getspnam_r.c89
-rw-r--r--src/passwd/lckpwdf.c11
-rw-r--r--src/passwd/pwf.h13
-rw-r--r--src/prng/__rand48_step.c14
-rw-r--r--src/prng/__seed48.c1
-rw-r--r--src/prng/drand48.c19
-rw-r--r--src/prng/lcong48.c9
-rw-r--r--src/prng/lrand48.c15
-rw-r--r--src/prng/mrand48.c15
-rw-r--r--src/prng/rand.c13
-rw-r--r--src/prng/rand_r.c6
-rw-r--r--src/prng/random.c8
-rw-r--r--src/prng/seed48.c12
-rw-r--r--src/prng/srand48.c6
-rw-r--r--src/prng/srandom.c8
-rw-r--r--src/process/execl.c20
-rw-r--r--src/process/execle.c22
-rw-r--r--src/process/execlp.c20
-rw-r--r--src/process/execv.c8
-rw-r--r--src/process/execve.c8
-rw-r--r--src/process/execvp.c34
-rw-r--r--src/process/fork.c9
-rw-r--r--src/process/system.c45
-rw-r--r--src/process/vfork.c8
-rw-r--r--src/process/wait.c6
-rw-r--r--src/process/waitid.c7
-rw-r--r--src/process/waitpid.c7
-rw-r--r--src/regex/fnmatch.c150
-rw-r--r--src/regex/glob.c238
-rw-r--r--src/regex/regcomp.c3362
-rw-r--r--src/regex/regerror.c75
-rw-r--r--src/regex/regexec.c1107
-rw-r--r--src/regex/tre-mem.c163
-rw-r--r--src/regex/tre.h269
-rw-r--r--src/select/poll.c12
-rw-r--r--src/select/pselect.c15
-rw-r--r--src/select/select.c12
-rw-r--r--src/setjmp/i386/longjmp.s22
-rw-r--r--src/setjmp/i386/setjmp.s23
-rw-r--r--src/setjmp/longjmp.c0
-rw-r--r--src/setjmp/setjmp.c0
-rw-r--r--src/signal/bsd_signal.c6
-rw-r--r--src/signal/getitimer.c12
-rw-r--r--src/signal/i386/sigsetjmp.s13
-rw-r--r--src/signal/kill.c7
-rw-r--r--src/signal/killpg.c11
-rw-r--r--src/signal/raise.c7
-rw-r--r--src/signal/setitimer.c15
-rw-r--r--src/signal/sigaction.c48
-rw-r--r--src/signal/sigaddset.c13
-rw-r--r--src/signal/sigaltstack.c8
-rw-r--r--src/signal/sigdelset.c13
-rw-r--r--src/signal/sigemptyset.c8
-rw-r--r--src/signal/sigfillset.c8
-rw-r--r--src/signal/sighold.c11
-rw-r--r--src/signal/sigignore.c12
-rw-r--r--src/signal/siginterrupt.c13
-rw-r--r--src/signal/sigismember.c12
-rw-r--r--src/signal/siglongjmp.c12
-rw-r--r--src/signal/signal.c13
-rw-r--r--src/signal/sigpause.c11
-rw-r--r--src/signal/sigpending.c7
-rw-r--r--src/signal/sigprocmask.c23
-rw-r--r--src/signal/sigqueue.c14
-rw-r--r--src/signal/sigrelse.c11
-rw-r--r--src/signal/sigrtmax.c4
-rw-r--r--src/signal/sigrtmin.c4
-rw-r--r--src/signal/sigset.c28
-rw-r--r--src/signal/sigsetjmp.c17
-rw-r--r--src/signal/sigsuspend.c7
-rw-r--r--src/signal/sigtimedwait.c12
-rw-r--r--src/signal/sigwait.c11
-rw-r--r--src/signal/sigwaitinfo.c7
-rw-r--r--src/stat/chmod.c7
-rw-r--r--src/stat/fchmod.c7
-rw-r--r--src/stat/fchmodat.c7
-rw-r--r--src/stat/fstat.c10
-rw-r--r--src/stat/fstatat.c10
-rw-r--r--src/stat/fstatvfs.c13
-rw-r--r--src/stat/lstat.c10
-rw-r--r--src/stat/mkdir.c7
-rw-r--r--src/stat/mkdirat.c7
-rw-r--r--src/stat/mkfifo.c6
-rw-r--r--src/stat/mkfifoat.c6
-rw-r--r--src/stat/mknod.c10
-rw-r--r--src/stat/mknodat.c7
-rw-r--r--src/stat/stat.c10
-rw-r--r--src/stat/statvfs.c13
-rw-r--r--src/stat/umask.c7
-rw-r--r--src/stdio/__fclose_ca.c6
-rw-r--r--src/stdio/__fdopen.c52
-rw-r--r--src/stdio/__fopen_rb_ca.c18
-rw-r--r--src/stdio/__fpending.c6
-rw-r--r--src/stdio/__ofl.c3
-rw-r--r--src/stdio/__overflow.c52
-rw-r--r--src/stdio/__scanf.c487
-rw-r--r--src/stdio/__scanf.h16
-rw-r--r--src/stdio/__stdio_close.c6
-rw-r--r--src/stdio/__stdio_read.c6
-rw-r--r--src/stdio/__stdio_seek.c15
-rw-r--r--src/stdio/__stdio_write.c9
-rw-r--r--src/stdio/__uflow.c7
-rw-r--r--src/stdio/__underflow.c38
-rw-r--r--src/stdio/asprintf.c14
-rw-r--r--src/stdio/clearerr.c10
-rw-r--r--src/stdio/dprintf.c12
-rw-r--r--src/stdio/fclose.c21
-rw-r--r--src/stdio/feof.c10
-rw-r--r--src/stdio/ferror.c10
-rw-r--r--src/stdio/fflush.c50
-rw-r--r--src/stdio/fgetc.c10
-rw-r--r--src/stdio/fgetpos.c11
-rw-r--r--src/stdio/fgets.c34
-rw-r--r--src/stdio/fgetwc.c51
-rw-r--r--src/stdio/fgetws.c27
-rw-r--r--src/stdio/fileno.c8
-rw-r--r--src/stdio/fmemopen.c16
-rw-r--r--src/stdio/fopen.c34
-rw-r--r--src/stdio/fprintf.c12
-rw-r--r--src/stdio/fputc.c10
-rw-r--r--src/stdio/fputs.c10
-rw-r--r--src/stdio/fputwc.c33
-rw-r--r--src/stdio/fputws.c23
-rw-r--r--src/stdio/fread.c49
-rw-r--r--src/stdio/freopen.c47
-rw-r--r--src/stdio/fscanf.c12
-rw-r--r--src/stdio/fseek.c38
-rw-r--r--src/stdio/fsetpos.c8
-rw-r--r--src/stdio/ftell.c35
-rw-r--r--src/stdio/fwide.c10
-rw-r--r--src/stdio/fwrite.c51
-rw-r--r--src/stdio/fwscanf.c13
-rw-r--r--src/stdio/getc.c6
-rw-r--r--src/stdio/getc_unlocked.c8
-rw-r--r--src/stdio/getchar.c6
-rw-r--r--src/stdio/getchar_unlocked.c6
-rw-r--r--src/stdio/getdelim.c59
-rw-r--r--src/stdio/getline.c6
-rw-r--r--src/stdio/gets.c8
-rw-r--r--src/stdio/getw.c7
-rw-r--r--src/stdio/getwc.c6
-rw-r--r--src/stdio/getwchar.c8
-rw-r--r--src/stdio/pclose.c10
-rw-r--r--src/stdio/perror.c27
-rw-r--r--src/stdio/popen.c43
-rw-r--r--src/stdio/printf.c12
-rw-r--r--src/stdio/putc.c8
-rw-r--r--src/stdio/putc_unlocked.c8
-rw-r--r--src/stdio/putchar.c6
-rw-r--r--src/stdio/putchar_unlocked.c7
-rw-r--r--src/stdio/puts.c6
-rw-r--r--src/stdio/putw.c6
-rw-r--r--src/stdio/putwc.c6
-rw-r--r--src/stdio/putwchar.c8
-rw-r--r--src/stdio/remove.c7
-rw-r--r--src/stdio/rename.c7
-rw-r--r--src/stdio/rewind.c6
-rw-r--r--src/stdio/scanf.c12
-rw-r--r--src/stdio/setbuf.c6
-rw-r--r--src/stdio/setvbuf.c22
-rw-r--r--src/stdio/snprintf.c13
-rw-r--r--src/stdio/sprintf.c12
-rw-r--r--src/stdio/sscanf.c12
-rw-r--r--src/stdio/stderr.c13
-rw-r--r--src/stdio/stdin.c13
-rw-r--r--src/stdio/stdout.c17
-rw-r--r--src/stdio/swscanf.c13
-rw-r--r--src/stdio/tempnam.c42
-rw-r--r--src/stdio/tmpfile.c23
-rw-r--r--src/stdio/tmpnam.c38
-rw-r--r--src/stdio/ungetc.c33
-rw-r--r--src/stdio/ungetwc.c45
-rw-r--r--src/stdio/vasprintf.c27
-rw-r--r--src/stdio/vdprintf.c14
-rw-r--r--src/stdio/vfprintf.c640
-rw-r--r--src/stdio/vfscanf.c43
-rw-r--r--src/stdio/vfwscanf.c28
-rw-r--r--src/stdio/vprintf.c6
-rw-r--r--src/stdio/vscanf.c7
-rw-r--r--src/stdio/vsnprintf.c33
-rw-r--r--src/stdio/vsprintf.c7
-rw-r--r--src/stdio/vsscanf.c21
-rw-r--r--src/stdio/vswscanf.c19
-rw-r--r--src/stdio/vwscanf.c8
-rw-r--r--src/stdio/wscanf.c13
-rw-r--r--src/stdlib/abs.c4
-rw-r--r--src/stdlib/atof.c6
-rw-r--r--src/stdlib/atoi.c15
-rw-r--r--src/stdlib/atol.c16
-rw-r--r--src/stdlib/atoll.c16
-rw-r--r--src/stdlib/bsearch.c20
-rw-r--r--src/stdlib/div.c6
-rw-r--r--src/stdlib/frexp.c23
-rw-r--r--src/stdlib/frexpf.c23
-rw-r--r--src/stdlib/frexpl.c25
-rw-r--r--src/stdlib/imaxabs.c6
-rw-r--r--src/stdlib/imaxdiv.c6
-rw-r--r--src/stdlib/labs.c4
-rw-r--r--src/stdlib/ldiv.c6
-rw-r--r--src/stdlib/llabs.c4
-rw-r--r--src/stdlib/lldiv.c6
-rw-r--r--src/stdlib/qsort.c50
-rw-r--r--src/stdlib/strtod.c6
-rw-r--r--src/stdlib/strtof.c6
-rw-r--r--src/stdlib/strtoimax.c25
-rw-r--r--src/stdlib/strtol.c17
-rw-r--r--src/stdlib/strtold.c93
-rw-r--r--src/stdlib/strtoll.c17
-rw-r--r--src/stdlib/strtoul.c14
-rw-r--r--src/stdlib/strtoull.c14
-rw-r--r--src/stdlib/strtoumax.c123
-rw-r--r--src/stdlib/wcstoimax.c24
-rw-r--r--src/stdlib/wcstol.c18
-rw-r--r--src/stdlib/wcstoll.c18
-rw-r--r--src/stdlib/wcstoul.c15
-rw-r--r--src/stdlib/wcstoull.c15
-rw-r--r--src/stdlib/wcstoumax.c47
-rw-r--r--src/string/bcmp.c7
-rw-r--r--src/string/bcopy.c7
-rw-r--r--src/string/bzero.c7
-rw-r--r--src/string/index.c7
-rw-r--r--src/string/memchr.c24
-rw-r--r--src/string/memcmp.c8
-rw-r--r--src/string/memcpy.c29
-rw-r--r--src/string/memmove.c14
-rw-r--r--src/string/mempcpy.c7
-rw-r--r--src/string/memset.c21
-rw-r--r--src/string/rindex.c7
-rw-r--r--src/string/stpcpy.c29
-rw-r--r--src/string/stpncpy.c32
-rw-r--r--src/string/strcasecmp.c9
-rw-r--r--src/string/strcasestr.c7
-rw-r--r--src/string/strcat.c7
-rw-r--r--src/string/strchr.c23
-rw-r--r--src/string/strchrnul.c7
-rw-r--r--src/string/strcmp.c7
-rw-r--r--src/string/strcpy.c16
-rw-r--r--src/string/strcspn.c20
-rw-r--r--src/string/strdup.c13
-rw-r--r--src/string/strerror_r.c11
-rw-r--r--src/string/strlcat.c8
-rw-r--r--src/string/strlcpy.c32
-rw-r--r--src/string/strlen.c21
-rw-r--r--src/string/strncasecmp.c10
-rw-r--r--src/string/strncat.c10
-rw-r--r--src/string/strncmp.c9
-rw-r--r--src/string/strncpy.c9
-rw-r--r--src/string/strndup.c12
-rw-r--r--src/string/strnlen.c7
-rw-r--r--src/string/strpbrk.c7
-rw-r--r--src/string/strrchr.c9
-rw-r--r--src/string/strsep.c12
-rw-r--r--src/string/strsignal.c98
-rw-r--r--src/string/strspn.c22
-rw-r--r--src/string/strstr.c166
-rw-r--r--src/string/strtok.c13
-rw-r--r--src/string/strtok_r.c12
-rw-r--r--src/string/swab.c13
-rw-r--r--src/string/wcscat.c7
-rw-r--r--src/string/wcschr.c8
-rw-r--r--src/string/wcscmp.c7
-rw-r--r--src/string/wcscpy.c8
-rw-r--r--src/string/wcscspn.c10
-rw-r--r--src/string/wcslen.c8
-rw-r--r--src/string/wcsncat.c10
-rw-r--r--src/string/wcsncmp.c7
-rw-r--r--src/string/wcsncpy.c9
-rw-r--r--src/string/wcspbrk.c7
-rw-r--r--src/string/wcsrchr.c8
-rw-r--r--src/string/wcsspn.c8
-rw-r--r--src/string/wcsstr.c117
-rw-r--r--src/string/wcswcs.c6
-rw-r--r--src/string/wmemchr.c8
-rw-r--r--src/string/wmemcmp.c8
-rw-r--r--src/string/wmemcpy.c9
-rw-r--r--src/string/wmemmove.c11
-rw-r--r--src/string/wmemset.c9
-rw-r--r--src/stub/utmpx.c30
-rw-r--r--src/temp/mkdtemp.c21
-rw-r--r--src/temp/mkstemp.c26
-rw-r--r--src/temp/mktemp.c29
-rw-r--r--src/termios/cfgetospeed.c12
-rw-r--r--src/termios/cfsetospeed.c22
-rw-r--r--src/termios/tcdrain.c7
-rw-r--r--src/termios/tcflow.c7
-rw-r--r--src/termios/tcflush.c7
-rw-r--r--src/termios/tcgetattr.c10
-rw-r--r--src/termios/tcgetsid.c10
-rw-r--r--src/termios/tcsendbreak.c8
-rw-r--r--src/termios/tcsetattr.c13
-rw-r--r--src/thread/__futex.c8
-rw-r--r--src/thread/__lock.c12
-rw-r--r--src/thread/__set_thread_area.c9
-rw-r--r--src/thread/__timedwait.c21
-rw-r--r--src/thread/__unmapself.c0
-rw-r--r--src/thread/__wait.c16
-rw-r--r--src/thread/__wake.c9
-rw-r--r--src/thread/cancellation.c22
-rw-r--r--src/thread/clone.c26
-rw-r--r--src/thread/i386/__unmapself.s22
-rw-r--r--src/thread/i386/clone.s35
-rw-r--r--src/thread/pthread_attr_destroy.c6
-rw-r--r--src/thread/pthread_attr_getdetachstate.c7
-rw-r--r--src/thread/pthread_attr_getguardsize.c7
-rw-r--r--src/thread/pthread_attr_getscope.c6
-rw-r--r--src/thread/pthread_attr_getstacksize.c7
-rw-r--r--src/thread/pthread_attr_init.c7
-rw-r--r--src/thread/pthread_attr_setdetachstate.c7
-rw-r--r--src/thread/pthread_attr_setguardsize.c8
-rw-r--r--src/thread/pthread_attr_setscope.c6
-rw-r--r--src/thread/pthread_attr_setstacksize.c8
-rw-r--r--src/thread/pthread_barrier_destroy.c6
-rw-r--r--src/thread/pthread_barrier_init.c8
-rw-r--r--src/thread/pthread_barrier_wait.c31
-rw-r--r--src/thread/pthread_cancel.c7
-rw-r--r--src/thread/pthread_cond_broadcast.c8
-rw-r--r--src/thread/pthread_cond_destroy.c6
-rw-r--r--src/thread/pthread_cond_init.c7
-rw-r--r--src/thread/pthread_cond_signal.c8
-rw-r--r--src/thread/pthread_cond_timedwait.c26
-rw-r--r--src/thread/pthread_cond_wait.c6
-rw-r--r--src/thread/pthread_create.c189
-rw-r--r--src/thread/pthread_detach.c11
-rw-r--r--src/thread/pthread_equal.c6
-rw-r--r--src/thread/pthread_exit.c25
-rw-r--r--src/thread/pthread_getspecific.c8
-rw-r--r--src/thread/pthread_join.c12
-rw-r--r--src/thread/pthread_key_create.c25
-rw-r--r--src/thread/pthread_key_delete.c7
-rw-r--r--src/thread/pthread_kill.c7
-rw-r--r--src/thread/pthread_mutex_destroy.c6
-rw-r--r--src/thread/pthread_mutex_init.c9
-rw-r--r--src/thread/pthread_mutex_lock.c9
-rw-r--r--src/thread/pthread_mutex_timedlock.c15
-rw-r--r--src/thread/pthread_mutex_trylock.c28
-rw-r--r--src/thread/pthread_mutex_unlock.c19
-rw-r--r--src/thread/pthread_mutexattr_destroy.c6
-rw-r--r--src/thread/pthread_mutexattr_gettype.c7
-rw-r--r--src/thread/pthread_mutexattr_init.c7
-rw-r--r--src/thread/pthread_mutexattr_settype.c8
-rw-r--r--src/thread/pthread_once.c38
-rw-r--r--src/thread/pthread_rwlock_destroy.c6
-rw-r--r--src/thread/pthread_rwlock_init.c9
-rw-r--r--src/thread/pthread_rwlock_rdlock.c8
-rw-r--r--src/thread/pthread_rwlock_timedrdlock.c15
-rw-r--r--src/thread/pthread_rwlock_timedwrlock.c17
-rw-r--r--src/thread/pthread_rwlock_tryrdlock.c13
-rw-r--r--src/thread/pthread_rwlock_trywrlock.c13
-rw-r--r--src/thread/pthread_rwlock_unlock.c17
-rw-r--r--src/thread/pthread_rwlock_wrlock.c13
-rw-r--r--src/thread/pthread_self.c39
-rw-r--r--src/thread/pthread_setcancelstate.c10
-rw-r--r--src/thread/pthread_setcanceltype.c10
-rw-r--r--src/thread/pthread_setspecific.c18
-rw-r--r--src/thread/pthread_spin_destroy.c6
-rw-r--r--src/thread/pthread_spin_init.c6
-rw-r--r--src/thread/pthread_spin_lock.c7
-rw-r--r--src/thread/pthread_spin_trylock.c6
-rw-r--r--src/thread/pthread_spin_unlock.c6
-rw-r--r--src/thread/pthread_testcancel.c7
-rw-r--r--src/time/__asctime.c27
-rw-r--r--src/time/__time.h9
-rw-r--r--src/time/__time_to_tm.c81
-rw-r--r--src/time/__tm_to_time.c33
-rw-r--r--src/time/asctime.c9
-rw-r--r--src/time/asctime_r.c8
-rw-r--r--src/time/clock.c9
-rw-r--r--src/time/clock_gettime.c7
-rw-r--r--src/time/ctime.c6
-rw-r--r--src/time/ctime_r.c8
-rw-r--r--src/time/difftime.c6
-rw-r--r--src/time/gettimeofday.c9
-rw-r--r--src/time/gmtime.c11
-rw-r--r--src/time/gmtime_r.c10
-rw-r--r--src/time/localtime.c12
-rw-r--r--src/time/localtime_r.c11
-rw-r--r--src/time/mktime.c24
-rw-r--r--src/time/nanosleep.c13
-rw-r--r--src/time/strftime.c172
-rw-r--r--src/time/strptime.c178
-rw-r--r--src/time/time.c12
-rw-r--r--src/time/times.c7
-rw-r--r--src/time/timezone.s27
-rw-r--r--src/time/tzset.c173
-rw-r--r--src/time/utime.c12
-rw-r--r--src/unistd/_exit.c7
-rw-r--r--src/unistd/access.c7
-rw-r--r--src/unistd/alarm.c7
-rw-r--r--src/unistd/chdir.c7
-rw-r--r--src/unistd/chown.c7
-rw-r--r--src/unistd/close.c11
-rw-r--r--src/unistd/confstr.c17
-rw-r--r--src/unistd/ctermid.c23
-rw-r--r--src/unistd/dup.c7
-rw-r--r--src/unistd/dup2.c7
-rw-r--r--src/unistd/faccessat.c7
-rw-r--r--src/unistd/fchdir.c7
-rw-r--r--src/unistd/fchown.c7
-rw-r--r--src/unistd/fchownat.c7
-rw-r--r--src/unistd/fdatasync.c7
-rw-r--r--src/unistd/fsync.c8
-rw-r--r--src/unistd/ftruncate.c15
-rw-r--r--src/unistd/getcwd.c8
-rw-r--r--src/unistd/getegid.c7
-rw-r--r--src/unistd/geteuid.c7
-rw-r--r--src/unistd/getgid.c7
-rw-r--r--src/unistd/getgroups.c8
-rw-r--r--src/unistd/gethostname.c14
-rw-r--r--src/unistd/getlogin.c7
-rw-r--r--src/unistd/getlogin_r.c13
-rw-r--r--src/unistd/getpgid.c7
-rw-r--r--src/unistd/getpgrp.c7
-rw-r--r--src/unistd/getpid.c7
-rw-r--r--src/unistd/getppid.c7
-rw-r--r--src/unistd/getsid.c7
-rw-r--r--src/unistd/getuid.c7
-rw-r--r--src/unistd/isatty.c8
-rw-r--r--src/unistd/lchown.c7
-rw-r--r--src/unistd/link.c7
-rw-r--r--src/unistd/linkat.c7
-rw-r--r--src/unistd/lseek.c16
-rw-r--r--src/unistd/nice.c7
-rw-r--r--src/unistd/pause.c12
-rw-r--r--src/unistd/pipe.c7
-rw-r--r--src/unistd/pread.c14
-rw-r--r--src/unistd/pwrite.c14
-rw-r--r--src/unistd/read.c12
-rw-r--r--src/unistd/readlink.c7
-rw-r--r--src/unistd/readlinkat.c7
-rw-r--r--src/unistd/readv.c12
-rw-r--r--src/unistd/renameat.c7
-rw-r--r--src/unistd/rmdir.c7
-rw-r--r--src/unistd/setegid.c6
-rw-r--r--src/unistd/seteuid.c6
-rw-r--r--src/unistd/setgid.c9
-rw-r--r--src/unistd/setpgid.c7
-rw-r--r--src/unistd/setpgrp.c6
-rw-r--r--src/unistd/setregid.c9
-rw-r--r--src/unistd/setreuid.c9
-rw-r--r--src/unistd/setsid.c7
-rw-r--r--src/unistd/setuid.c9
-rw-r--r--src/unistd/sleep.c10
-rw-r--r--src/unistd/symlink.c7
-rw-r--r--src/unistd/symlinkat.c7
-rw-r--r--src/unistd/sync.c7
-rw-r--r--src/unistd/tcgetpgrp.c11
-rw-r--r--src/unistd/tcsetpgrp.c9
-rw-r--r--src/unistd/truncate.c15
-rw-r--r--src/unistd/ttyname.c14
-rw-r--r--src/unistd/ttyname_r.c19
-rw-r--r--src/unistd/ualarm.c8
-rw-r--r--src/unistd/unlink.c7
-rw-r--r--src/unistd/unlinkat.c7
-rw-r--r--src/unistd/usleep.c11
-rw-r--r--src/unistd/write.c12
-rw-r--r--src/unistd/writev.c12
-rw-r--r--tools/gen-musl-gcc.sh30
1021 files changed, 45711 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..223ede7d
--- /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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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
+
+ 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
index 00000000..30a74a21
--- /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
index 00000000..2470a5bf
--- /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
index 00000000..e4235cb5
--- /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
index 00000000..a57541c6
--- /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
index 00000000..e69de29b
--- /dev/null
+++ b/crt/crt1.c
diff --git a/crt/crti.c b/crt/crti.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/crt/crti.c
diff --git a/crt/crtn.c b/crt/crtn.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/crt/crtn.c
diff --git a/crt/i386/crt1.s b/crt/i386/crt1.s
new file mode 100644
index 00000000..050adec8
--- /dev/null
+++ b/crt/i386/crt1.s
@@ -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
index 00000000..51205522
--- /dev/null
+++ b/dist/config.mak
@@ -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
index 00000000..ac78e460
--- /dev/null
+++ b/include/alloca.h
@@ -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
index 00000000..93427130
--- /dev/null
+++ b/include/arpa/inet.h
@@ -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
index 00000000..0f854600
--- /dev/null
+++ b/include/arpa/nameser.h
@@ -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
index 00000000..e2ad9742
--- /dev/null
+++ b/include/arpa/telnet.h
@@ -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
index 00000000..bad2ccd0
--- /dev/null
+++ b/include/assert.h
@@ -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
index 00000000..595bf13e
--- /dev/null
+++ b/include/bits/alltypes.h.sh
@@ -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
index 00000000..172c338f
--- /dev/null
+++ b/include/bits/endian.h
@@ -0,0 +1 @@
+#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/include/bits/errno.h b/include/bits/errno.h
new file mode 100644
index 00000000..fddea5ef
--- /dev/null
+++ b/include/bits/errno.h
@@ -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
index 00000000..550152fd
--- /dev/null
+++ b/include/bits/fcntl.h
@@ -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
index 00000000..24df0417
--- /dev/null
+++ b/include/bits/fenv.h
@@ -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
index 00000000..162b3e46
--- /dev/null
+++ b/include/bits/float.h
@@ -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
index 00000000..53ca31ca
--- /dev/null
+++ b/include/bits/in.h
@@ -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
index 00000000..bb63ffb4
--- /dev/null
+++ b/include/bits/ioctl.h
@@ -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
index 00000000..8e3ef9b9
--- /dev/null
+++ b/include/bits/ipc.h
@@ -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
index 00000000..48fdd7a1
--- /dev/null
+++ b/include/bits/limits.h
@@ -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
index 00000000..e02d488c
--- /dev/null
+++ b/include/bits/mman.h
@@ -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
index 00000000..30a38714
--- /dev/null
+++ b/include/bits/posix.h
@@ -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
index 00000000..7d19065d
--- /dev/null
+++ b/include/bits/pthread.h
@@ -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
index 00000000..8bc2582d
--- /dev/null
+++ b/include/bits/reg.h
@@ -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
index 00000000..b6595bd2
--- /dev/null
+++ b/include/bits/setjmp.h
@@ -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
index 00000000..46774237
--- /dev/null
+++ b/include/bits/shm.h
@@ -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
index 00000000..2427f37a
--- /dev/null
+++ b/include/bits/signal.h
@@ -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
index 00000000..7a51f792
--- /dev/null
+++ b/include/bits/socket.h
@@ -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
index 00000000..1ef34698
--- /dev/null
+++ b/include/bits/stat.h
@@ -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
index 00000000..9dda4400
--- /dev/null
+++ b/include/bits/statfs.h
@@ -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
index 00000000..8e21a8cb
--- /dev/null
+++ b/include/bits/stdint.h
@@ -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
index 00000000..0afd8b40
--- /dev/null
+++ b/include/bits/stdio.h
@@ -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
index 00000000..da29022d
--- /dev/null
+++ b/include/bits/sysmacros.h
@@ -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
index 00000000..923231b2
--- /dev/null
+++ b/include/bits/tcp.h
@@ -0,0 +1 @@
+#define TCP_NODELAY 1
diff --git a/include/bits/termios.h b/include/bits/termios.h
new file mode 100644
index 00000000..316baeb2
--- /dev/null
+++ b/include/bits/termios.h
@@ -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
index 00000000..43252653
--- /dev/null
+++ b/include/bits/uio.h
@@ -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
index 00000000..13ff027b
--- /dev/null
+++ b/include/bits/user.h
@@ -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
index 00000000..ca9b57e0
--- /dev/null
+++ b/include/bits/wait.h
@@ -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
index 00000000..34a80238
--- /dev/null
+++ b/include/bits/wexitstatus.h
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/include/byteswap.h
diff --git a/include/cpio.h b/include/cpio.h
new file mode 100644
index 00000000..39a1f8bb
--- /dev/null
+++ b/include/cpio.h
@@ -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
index 00000000..02f81fa7
--- /dev/null
+++ b/include/ctype.h
@@ -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
index 00000000..a9170936
--- /dev/null
+++ b/include/dirent.h
@@ -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
index 00000000..81b829c8
--- /dev/null
+++ b/include/dlfcn.h
@@ -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
index 00000000..b011e784
--- /dev/null
+++ b/include/elf.h
@@ -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
index 00000000..bcf67662
--- /dev/null
+++ b/include/endian.h
@@ -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
index 00000000..d9c2c9c7
--- /dev/null
+++ b/include/errno.h
@@ -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
index 00000000..61a6cb55
--- /dev/null
+++ b/include/fcntl.h
@@ -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
index 00000000..851afb66
--- /dev/null
+++ b/include/features.h
@@ -0,0 +1 @@
+#warning "features.h is bogus"
diff --git a/include/fenv.h b/include/fenv.h
new file mode 100644
index 00000000..05de990c
--- /dev/null
+++ b/include/fenv.h
@@ -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
index 00000000..ef91f37d
--- /dev/null
+++ b/include/float.h
@@ -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
index 00000000..b7aee504
--- /dev/null
+++ b/include/fnmatch.h
@@ -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
index 00000000..8d31c6d9
--- /dev/null
+++ b/include/ftw.h
@@ -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
index 00000000..0de05aef
--- /dev/null
+++ b/include/getopt.h
@@ -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
index 00000000..185912df
--- /dev/null
+++ b/include/glob.h
@@ -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
index 00000000..d4a3526a
--- /dev/null
+++ b/include/grp.h
@@ -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
index 00000000..f2ccaf8c
--- /dev/null
+++ b/include/iconv.h
@@ -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
index 00000000..13ba6e0f
--- /dev/null
+++ b/include/inttypes.h
@@ -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
index 00000000..4d9e0997
--- /dev/null
+++ b/include/langinfo.h
@@ -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
index 00000000..7c7fd9c6
--- /dev/null
+++ b/include/libgen.h
@@ -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
index 00000000..a2dada67
--- /dev/null
+++ b/include/libintl.h
@@ -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
index 00000000..4499afbf
--- /dev/null
+++ b/include/limits.h
@@ -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
index 00000000..41aad407
--- /dev/null
+++ b/include/linux/loop.h
@@ -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
index 00000000..e6a89ef2
--- /dev/null
+++ b/include/linux/version.h
@@ -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
index 00000000..70230237
--- /dev/null
+++ b/include/locale.h
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/include/malloc.h
diff --git a/include/math.h b/include/math.h
new file mode 100644
index 00000000..cc9befb7
--- /dev/null
+++ b/include/math.h
@@ -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
index 00000000..c0fed7fc
--- /dev/null
+++ b/include/mntent.h
@@ -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
index 00000000..a536502d
--- /dev/null
+++ b/include/net/ethernet.h
@@ -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
index 00000000..2ae5f89e
--- /dev/null
+++ b/include/net/if.h
@@ -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
index 00000000..bb5eadf1
--- /dev/null
+++ b/include/net/if_arp.h
@@ -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
index 00000000..3aaab978
--- /dev/null
+++ b/include/net/route.h
@@ -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
index 00000000..5f1dd3f1
--- /dev/null
+++ b/include/netdb.h
@@ -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
index 00000000..01269e7d
--- /dev/null
+++ b/include/netinet/icmp6.h
@@ -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
index 00000000..65a838ac
--- /dev/null
+++ b/include/netinet/if_ether.h
@@ -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
index 00000000..a641f6a6
--- /dev/null
+++ b/include/netinet/in.h
@@ -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
index 00000000..41187414
--- /dev/null
+++ b/include/netinet/ip.h
@@ -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
index 00000000..a4347a53
--- /dev/null
+++ b/include/netinet/ip6.h
@@ -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
index 00000000..2f4a86dd
--- /dev/null
+++ b/include/netinet/ip_icmp.h
@@ -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
index 00000000..ea32ca07
--- /dev/null
+++ b/include/netinet/tcp.h
@@ -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
index 00000000..15b91454
--- /dev/null
+++ b/include/netinet/udp.h
@@ -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
index 00000000..ca61efb6
--- /dev/null
+++ b/include/nl_types.h
@@ -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
index 00000000..8a38ba7b
--- /dev/null
+++ b/include/paths.h
@@ -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
index 00000000..f868ab57
--- /dev/null
+++ b/include/poll.h
@@ -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
index 00000000..ce6273d2
--- /dev/null
+++ b/include/pthread.h
@@ -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
index 00000000..9444e5ec
--- /dev/null
+++ b/include/pty.h
@@ -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
index 00000000..5abfbfd5
--- /dev/null
+++ b/include/pwd.h
@@ -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
index 00000000..3673bfa7
--- /dev/null
+++ b/include/regex.h
@@ -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
index 00000000..3b77fc7b
--- /dev/null
+++ b/include/resolv.h
@@ -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
index 00000000..4d8bd3db
--- /dev/null
+++ b/include/sched.h
@@ -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
index 00000000..9254ed0c
--- /dev/null
+++ b/include/search.h
@@ -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
index 00000000..5b68986d
--- /dev/null
+++ b/include/semaphore.h
@@ -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
index 00000000..6288c846
--- /dev/null
+++ b/include/setjmp.h
@@ -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
index 00000000..2b1be413
--- /dev/null
+++ b/include/shadow.h
@@ -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
index 00000000..540236a5
--- /dev/null
+++ b/include/signal.h
@@ -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
index 00000000..cb18778b
--- /dev/null
+++ b/include/stdarg.h
@@ -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
index 00000000..3d8fbf2a
--- /dev/null
+++ b/include/stdbool.h
@@ -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
index 00000000..dbf5a4ae
--- /dev/null
+++ b/include/stddef.h
@@ -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
index 00000000..4d24fd2e
--- /dev/null
+++ b/include/stdint.h
@@ -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
index 00000000..b00436d9
--- /dev/null
+++ b/include/stdio.h
@@ -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
index 00000000..6dbbc9cb
--- /dev/null
+++ b/include/stdlib.h
@@ -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
index 00000000..f189c082
--- /dev/null
+++ b/include/string.h
@@ -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
index 00000000..059e3309
--- /dev/null
+++ b/include/strings.h
@@ -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
index 00000000..80776ba6
--- /dev/null
+++ b/include/stropts.h
@@ -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
index 00000000..3530a9ac
--- /dev/null
+++ b/include/sys/epoll.h
@@ -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
index 00000000..8b2eb01a
--- /dev/null
+++ b/include/sys/file.h
@@ -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
index 00000000..d0415b3d
--- /dev/null
+++ b/include/sys/ioctl.h
@@ -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
index 00000000..9de9f3e7
--- /dev/null
+++ b/include/sys/ipc.h
@@ -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
index 00000000..793fd59f
--- /dev/null
+++ b/include/sys/kd.h
@@ -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
index 00000000..aa66684e
--- /dev/null
+++ b/include/sys/klog.h
@@ -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
index 00000000..6aede8bd
--- /dev/null
+++ b/include/sys/mman.h
@@ -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
index 00000000..2c685f67
--- /dev/null
+++ b/include/sys/mount.h
@@ -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
index 00000000..9fc42bcd
--- /dev/null
+++ b/include/sys/msg.h
@@ -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
index 00000000..ded4a16b
--- /dev/null
+++ b/include/sys/param.h
@@ -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
index 00000000..779ec774
--- /dev/null
+++ b/include/sys/poll.h
@@ -0,0 +1 @@
+#include <poll.h>
diff --git a/include/sys/prctl.h b/include/sys/prctl.h
new file mode 100644
index 00000000..cd34848a
--- /dev/null
+++ b/include/sys/prctl.h
@@ -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
index 00000000..20b4847c
--- /dev/null
+++ b/include/sys/procfs.h
@@ -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
index 00000000..0459d1b6
--- /dev/null
+++ b/include/sys/ptrace.h
@@ -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
index 00000000..26cc3088
--- /dev/null
+++ b/include/sys/reboot.h
@@ -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
index 00000000..ebf3fff4
--- /dev/null
+++ b/include/sys/reg.h
@@ -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
index 00000000..99e383c4
--- /dev/null
+++ b/include/sys/resource.h
@@ -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
index 00000000..c44eada4
--- /dev/null
+++ b/include/sys/select.h
@@ -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
index 00000000..15d8b685
--- /dev/null
+++ b/include/sys/sem.h
@@ -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
index 00000000..6ebb9412
--- /dev/null
+++ b/include/sys/shm.h
@@ -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
index 00000000..895664bf
--- /dev/null
+++ b/include/sys/signalfd.h
@@ -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
index 00000000..78c93056
--- /dev/null
+++ b/include/sys/socket.h
@@ -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
index 00000000..fade986f
--- /dev/null
+++ b/include/sys/soundcard.h
@@ -0,0 +1 @@
+#include <linux/soundcard.h>
diff --git a/include/sys/stat.h b/include/sys/stat.h
new file mode 100644
index 00000000..36575b0e
--- /dev/null
+++ b/include/sys/stat.h
@@ -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
index 00000000..7eaa7e7c
--- /dev/null
+++ b/include/sys/statfs.h
@@ -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
index 00000000..6479be6f
--- /dev/null
+++ b/include/sys/statvfs.h
@@ -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
index 00000000..5b5bc02f
--- /dev/null
+++ b/include/sys/stropts.h
@@ -0,0 +1 @@
+#include <stropts.h>
diff --git a/include/sys/swap.h b/include/sys/swap.h
new file mode 100644
index 00000000..c5824f1d
--- /dev/null
+++ b/include/sys/swap.h
@@ -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
index 00000000..af5ca8ba
--- /dev/null
+++ b/include/sys/sysctl.h
@@ -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
index 00000000..ca52088a
--- /dev/null
+++ b/include/sys/sysinfo.h
@@ -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
index 00000000..79eba3be
--- /dev/null
+++ b/include/sys/sysmacros.h
@@ -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
index 00000000..9b3bfb99
--- /dev/null
+++ b/include/sys/time.h
@@ -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
index 00000000..aca743d3
--- /dev/null
+++ b/include/sys/times.h
@@ -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
index 00000000..8be19e6b
--- /dev/null
+++ b/include/sys/types.h
@@ -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
index 00000000..5fdbd63d
--- /dev/null
+++ b/include/sys/ucontext.h
@@ -0,0 +1 @@
+#include <ucontext.h>
diff --git a/include/sys/uio.h b/include/sys/uio.h
new file mode 100644
index 00000000..7b068c0c
--- /dev/null
+++ b/include/sys/uio.h
@@ -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
index 00000000..769dac6b
--- /dev/null
+++ b/include/sys/un.h
@@ -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
index 00000000..24ac9400
--- /dev/null
+++ b/include/sys/user.h
@@ -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
index 00000000..383e8251
--- /dev/null
+++ b/include/sys/utsname.h
@@ -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
index 00000000..a899db27
--- /dev/null
+++ b/include/sys/vfs.h
@@ -0,0 +1 @@
+#include <sys/statfs.h>
diff --git a/include/sys/vt.h b/include/sys/vt.h
new file mode 100644
index 00000000..834abfbc
--- /dev/null
+++ b/include/sys/vt.h
@@ -0,0 +1 @@
+#include <linux/vt.h>
diff --git a/include/sys/wait.h b/include/sys/wait.h
new file mode 100644
index 00000000..a1851530
--- /dev/null
+++ b/include/sys/wait.h
@@ -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
index 00000000..119c9bcb
--- /dev/null
+++ b/include/syslog.h
@@ -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
index 00000000..be589842
--- /dev/null
+++ b/include/tar.h
@@ -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
index 00000000..4c465627
--- /dev/null
+++ b/include/termios.h
@@ -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
index 00000000..e6cfb73d
--- /dev/null
+++ b/include/time.h
@@ -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
index 00000000..db335677
--- /dev/null
+++ b/include/ucontext.h
@@ -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
index 00000000..efdcd311
--- /dev/null
+++ b/include/ulimit.h
@@ -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
index 00000000..5ad0704b
--- /dev/null
+++ b/include/unistd.h
@@ -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
index 00000000..ec82e0f3
--- /dev/null
+++ b/include/utime.h
@@ -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
index 00000000..f60ff883
--- /dev/null
+++ b/include/utmp.h
@@ -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
index 00000000..9a2e3075
--- /dev/null
+++ b/include/utmpx.h
@@ -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
index 00000000..3f325bff
--- /dev/null
+++ b/include/wchar.h
@@ -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
index 00000000..8b6c9d9d
--- /dev/null
+++ b/include/wctype.h
@@ -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
index 00000000..91995c44
--- /dev/null
+++ b/include/wordexp.h
@@ -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
index 00000000..af7e4d3b
--- /dev/null
+++ b/src/conf/fpathconf.c
@@ -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
index 00000000..01e19c59
--- /dev/null
+++ b/src/conf/pathconf.c
@@ -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
index 00000000..cdaeb2a6
--- /dev/null
+++ b/src/conf/sysconf.c
@@ -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
index 00000000..42e4ee71
--- /dev/null
+++ b/src/ctype/__ctype_get_mb_cur_max.c
@@ -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
index 00000000..e3d2cf0b
--- /dev/null
+++ b/src/ctype/isalnum.c
@@ -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
index 00000000..53e115c2
--- /dev/null
+++ b/src/ctype/isalpha.c
@@ -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
index 00000000..3af0a10d
--- /dev/null
+++ b/src/ctype/isascii.c
@@ -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
index 00000000..957400b2
--- /dev/null
+++ b/src/ctype/isblank.c
@@ -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
index 00000000..92ed7f0e
--- /dev/null
+++ b/src/ctype/iscntrl.c
@@ -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
index 00000000..0bc82a6d
--- /dev/null
+++ b/src/ctype/isdigit.c
@@ -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
index 00000000..98979d1e
--- /dev/null
+++ b/src/ctype/isgraph.c
@@ -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
index 00000000..d72fb212
--- /dev/null
+++ b/src/ctype/islower.c
@@ -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
index 00000000..504e66ed
--- /dev/null
+++ b/src/ctype/isprint.c
@@ -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
index 00000000..fc455352
--- /dev/null
+++ b/src/ctype/ispunct.c
@@ -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
index 00000000..8e535aa1
--- /dev/null
+++ b/src/ctype/isspace.c
@@ -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
index 00000000..f09d88c5
--- /dev/null
+++ b/src/ctype/isupper.c
@@ -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
index 00000000..d3b56674
--- /dev/null
+++ b/src/ctype/iswalnum.c
@@ -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
index 00000000..0f031eac
--- /dev/null
+++ b/src/ctype/iswalpha.c
@@ -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
index 00000000..bc6196f2
--- /dev/null
+++ b/src/ctype/iswblank.c
@@ -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
index 00000000..93942b08
--- /dev/null
+++ b/src/ctype/iswcntrl.c
@@ -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
index 00000000..d917975b
--- /dev/null
+++ b/src/ctype/iswctype.c
@@ -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
index 00000000..0487145f
--- /dev/null
+++ b/src/ctype/iswdigit.c
@@ -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
index 00000000..fdc97853
--- /dev/null
+++ b/src/ctype/iswgraph.c
@@ -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
index 00000000..0a568e77
--- /dev/null
+++ b/src/ctype/iswlower.c
@@ -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
index 00000000..7717671a
--- /dev/null
+++ b/src/ctype/iswprint.c
@@ -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
index 00000000..1414c30c
--- /dev/null
+++ b/src/ctype/iswpunct.c
@@ -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
index 00000000..68a17437
--- /dev/null
+++ b/src/ctype/iswspace.c
@@ -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
index 00000000..eae59a75
--- /dev/null
+++ b/src/ctype/iswupper.c
@@ -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
index 00000000..229a469f
--- /dev/null
+++ b/src/ctype/iswxdigit.c
@@ -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
index 00000000..ae68a3dc
--- /dev/null
+++ b/src/ctype/isxdigit.c
@@ -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
index 00000000..f0e48e8e
--- /dev/null
+++ b/src/ctype/toascii.c
@@ -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
index 00000000..b56f3c50
--- /dev/null
+++ b/src/ctype/tolower.c
@@ -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
index 00000000..1799f030
--- /dev/null
+++ b/src/ctype/toupper.c
@@ -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
index 00000000..0b1eed04
--- /dev/null
+++ b/src/ctype/towctrans.c
@@ -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
index 00000000..5c8a5a4d
--- /dev/null
+++ b/src/ctype/wcswidth.c
@@ -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
index 00000000..03e9fd6a
--- /dev/null
+++ b/src/ctype/wctrans.c
@@ -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
index 00000000..ebc560a5
--- /dev/null
+++ b/src/ctype/wcwidth.c
@@ -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
index 00000000..07b3ee68
--- /dev/null
+++ b/src/dirent/__dirent.h
@@ -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
index 00000000..4195430b
--- /dev/null
+++ b/src/dirent/__getdents.c
@@ -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
index 00000000..42050fb7
--- /dev/null
+++ b/src/dirent/alphasort.c
@@ -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
index 00000000..81e9591c
--- /dev/null
+++ b/src/dirent/closedir.c
@@ -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
index 00000000..6c860073
--- /dev/null
+++ b/src/dirent/dirfd.c
@@ -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
index 00000000..c4b8e61d
--- /dev/null
+++ b/src/dirent/fdopendir.c
@@ -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
index 00000000..cefe6ce7
--- /dev/null
+++ b/src/dirent/opendir.c
@@ -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
index 00000000..1aeb25a5
--- /dev/null
+++ b/src/dirent/readdir.c
@@ -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
index 00000000..58f60325
--- /dev/null
+++ b/src/dirent/readdir_r.c
@@ -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
index 00000000..c6138f7c
--- /dev/null
+++ b/src/dirent/rewinddir.c
@@ -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
index 00000000..6a0a9993
--- /dev/null
+++ b/src/dirent/scandir.c
@@ -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
index 00000000..81a0e331
--- /dev/null
+++ b/src/dirent/seekdir.c
@@ -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
index 00000000..cf25acff
--- /dev/null
+++ b/src/dirent/telldir.c
@@ -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
index 00000000..d7bd5e50
--- /dev/null
+++ b/src/env/__environ.c
@@ -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
index 00000000..70af77b5
--- /dev/null
+++ b/src/env/__libc_start_main.c
@@ -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
index 00000000..a2475ce7
--- /dev/null
+++ b/src/env/clearenv.c
@@ -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
index 00000000..00c1bce0
--- /dev/null
+++ b/src/env/getenv.c
@@ -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
index 00000000..181a4181
--- /dev/null
+++ b/src/env/putenv.c
@@ -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
index 00000000..03e165c8
--- /dev/null
+++ b/src/env/setenv.c
@@ -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
index 00000000..7493d970
--- /dev/null
+++ b/src/env/unsetenv.c
@@ -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
index 00000000..0a220b63
--- /dev/null
+++ b/src/errno/__errno_location.c
@@ -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
index 00000000..00eaf938
--- /dev/null
+++ b/src/errno/__strerror.h
@@ -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
index 00000000..b8fbc6db
--- /dev/null
+++ b/src/errno/strerror.c
@@ -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
index 00000000..8ef85a8f
--- /dev/null
+++ b/src/exit/_Exit.c
@@ -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
index 00000000..9a1c3d40
--- /dev/null
+++ b/src/exit/abort.c
@@ -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
index 00000000..e87442a7
--- /dev/null
+++ b/src/exit/assert.c
@@ -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
index 00000000..49c060e6
--- /dev/null
+++ b/src/exit/atexit.c
@@ -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
index 00000000..d0c1bfc1
--- /dev/null
+++ b/src/exit/exit.c
@@ -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
index 00000000..be05faae
--- /dev/null
+++ b/src/fcntl/creat.c
@@ -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
index 00000000..464dbf00
--- /dev/null
+++ b/src/fcntl/fcntl.c
@@ -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
index 00000000..4c1a591d
--- /dev/null
+++ b/src/fcntl/open.c
@@ -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
index 00000000..eefa0901
--- /dev/null
+++ b/src/fcntl/openat.c
@@ -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
index 00000000..a15f8c2a
--- /dev/null
+++ b/src/internal/atomic.h
@@ -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
index 00000000..cc84aeb4
--- /dev/null
+++ b/src/internal/clone.h
@@ -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
index 00000000..c0453822
--- /dev/null
+++ b/src/internal/futex.h
@@ -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
index 00000000..5e8e9d95
--- /dev/null
+++ b/src/internal/libc.c
@@ -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
index 00000000..e353f363
--- /dev/null
+++ b/src/internal/libc.h
@@ -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
index 00000000..c268124f
--- /dev/null
+++ b/src/internal/locale_impl.h
@@ -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
index 00000000..b7892103
--- /dev/null
+++ b/src/internal/pthread_impl.h
@@ -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
index 00000000..1e9159f6
--- /dev/null
+++ b/src/internal/stdio_impl.h
@@ -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
index 00000000..4f159e0b
--- /dev/null
+++ b/src/internal/syscall.c
@@ -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
index 00000000..4b3c0a73
--- /dev/null
+++ b/src/internal/syscall.h
@@ -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
index 00000000..7c7c3a17
--- /dev/null
+++ b/src/internal/util.h
@@ -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
index 00000000..cd6002ed
--- /dev/null
+++ b/src/ipc/ftok.c
@@ -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
index 00000000..9edd5ecf
--- /dev/null
+++ b/src/ipc/ipc.h
@@ -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
index 00000000..7ada116b
--- /dev/null
+++ b/src/ipc/semctl.c
@@ -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
index 00000000..2dcf6eac
--- /dev/null
+++ b/src/ipc/semget.c
@@ -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
index 00000000..48d8a654
--- /dev/null
+++ b/src/ipc/semop.c
@@ -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
index 00000000..ff65b6a4
--- /dev/null
+++ b/src/ipc/shmat.c
@@ -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
index 00000000..da357fa8
--- /dev/null
+++ b/src/ipc/shmctl.c
@@ -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
index 00000000..e04188f9
--- /dev/null
+++ b/src/ipc/shmdt.c
@@ -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
index 00000000..86e254af
--- /dev/null
+++ b/src/ipc/shmget.c
@@ -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
index 00000000..3c2982c6
--- /dev/null
+++ b/src/linux/brk.c
@@ -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
index 00000000..b5af62dc
--- /dev/null
+++ b/src/linux/chroot.c
@@ -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
index 00000000..632d1203
--- /dev/null
+++ b/src/linux/daemon.c
@@ -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
index 00000000..c9dea8ce
--- /dev/null
+++ b/src/linux/epoll_create.c
@@ -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
index 00000000..2e82e995
--- /dev/null
+++ b/src/linux/epoll_create1.c
@@ -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
index 00000000..4214f407
--- /dev/null
+++ b/src/linux/epoll_ctl.c
@@ -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
index 00000000..5aaacba6
--- /dev/null
+++ b/src/linux/epoll_pwait.c
@@ -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
index 00000000..8a68ebdd
--- /dev/null
+++ b/src/linux/epoll_wait.c
@@ -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
index 00000000..623a6af3
--- /dev/null
+++ b/src/linux/getdtablesize.c
@@ -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
index 00000000..ea65611a
--- /dev/null
+++ b/src/linux/gethostid.c
@@ -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
index 00000000..d80cd1b6
--- /dev/null
+++ b/src/linux/getopt_long.c
@@ -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
index 00000000..5ede652b
--- /dev/null
+++ b/src/linux/getpagesize.c
@@ -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
index 00000000..d439a2a5
--- /dev/null
+++ b/src/linux/getpass.c
@@ -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
index 00000000..ef9bc10a
--- /dev/null
+++ b/src/linux/initgroups.c
@@ -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
index 00000000..6c288aff
--- /dev/null
+++ b/src/linux/klogctl.c
@@ -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
index 00000000..e3735666
--- /dev/null
+++ b/src/linux/mntent.c
@@ -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
index 00000000..61299d48
--- /dev/null
+++ b/src/linux/mount.c
@@ -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
index 00000000..d5516830
--- /dev/null
+++ b/src/linux/prctl.c
@@ -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
index 00000000..68830d8e
--- /dev/null
+++ b/src/linux/reboot.c
@@ -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
index 00000000..56f60d1b
--- /dev/null
+++ b/src/linux/sbrk.c
@@ -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
index 00000000..bfbc40ae
--- /dev/null
+++ b/src/linux/sendfile.c
@@ -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
index 00000000..2368aa0d
--- /dev/null
+++ b/src/linux/setgroups.c
@@ -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
index 00000000..f61e0cb4
--- /dev/null
+++ b/src/linux/sethostname.c
@@ -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
index 00000000..bd7e4104
--- /dev/null
+++ b/src/linux/settimeofday.c
@@ -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
index 00000000..ecda263e
--- /dev/null
+++ b/src/linux/signalfd.c
@@ -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
index 00000000..ec3ba821
--- /dev/null
+++ b/src/linux/stime.c
@@ -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
index 00000000..f6fa794e
--- /dev/null
+++ b/src/linux/swapoff.c
@@ -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
index 00000000..13d2876b
--- /dev/null
+++ b/src/linux/swapon.c
@@ -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
index 00000000..98669472
--- /dev/null
+++ b/src/linux/sysinfo.c
@@ -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
index 00000000..c35f994d
--- /dev/null
+++ b/src/linux/umount.c
@@ -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
index 00000000..cab93fd0
--- /dev/null
+++ b/src/linux/umount2.c
@@ -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
index 00000000..99a3b2b8
--- /dev/null
+++ b/src/linux/utimes.c
@@ -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
index 00000000..dd63707c
--- /dev/null
+++ b/src/linux/wait3.c
@@ -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
index 00000000..dda942d3
--- /dev/null
+++ b/src/linux/wait4.c
@@ -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
index 00000000..02cd3e5c
--- /dev/null
+++ b/src/locale/catclose.c
@@ -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
index 00000000..bbee8986
--- /dev/null
+++ b/src/locale/catgets.c
@@ -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
index 00000000..4423c4d9
--- /dev/null
+++ b/src/locale/catopen.c
@@ -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
index 00000000..dd445d46
--- /dev/null
+++ b/src/locale/duplocale.c
@@ -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
index 00000000..4e089f22
--- /dev/null
+++ b/src/locale/freelocale.c
@@ -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
index 00000000..4e46c7e4
--- /dev/null
+++ b/src/locale/iconv.c
@@ -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
index 00000000..964f7da1
--- /dev/null
+++ b/src/locale/intl.c
@@ -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
index 00000000..b8a6eef3
--- /dev/null
+++ b/src/locale/isalnum_l.c
@@ -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
index 00000000..2e1205c6
--- /dev/null
+++ b/src/locale/isalpha_l.c
@@ -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
index 00000000..27479aa1
--- /dev/null
+++ b/src/locale/isblank_l.c
@@ -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
index 00000000..ca596fa9
--- /dev/null
+++ b/src/locale/iscntrl_l.c
@@ -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
index 00000000..c8ae7bd3
--- /dev/null
+++ b/src/locale/isdigit_l.c
@@ -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
index 00000000..713a86e6
--- /dev/null
+++ b/src/locale/isgraph_l.c
@@ -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
index 00000000..25ec97a1
--- /dev/null
+++ b/src/locale/islower_l.c
@@ -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
index 00000000..79ef3514
--- /dev/null
+++ b/src/locale/isprint_l.c
@@ -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
index 00000000..1c0bd046
--- /dev/null
+++ b/src/locale/ispunct_l.c
@@ -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
index 00000000..e1a0efed
--- /dev/null
+++ b/src/locale/isspace_l.c
@@ -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
index 00000000..11ba7036
--- /dev/null
+++ b/src/locale/isupper_l.c
@@ -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
index 00000000..68649d09
--- /dev/null
+++ b/src/locale/isxdigit_l.c
@@ -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
index 00000000..f7f56012
--- /dev/null
+++ b/src/locale/langinfo.c
@@ -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
index 00000000..d79d1c07
--- /dev/null
+++ b/src/locale/localeconv.c
@@ -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
index 00000000..986e796f
--- /dev/null
+++ b/src/locale/newlocale.c
@@ -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
index 00000000..bb3a2c46
--- /dev/null
+++ b/src/locale/nl_langinfo.c
@@ -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
index 00000000..28f29b80
--- /dev/null
+++ b/src/locale/setlocale.c
@@ -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
index 00000000..30bccd62
--- /dev/null
+++ b/src/locale/strcoll.c
@@ -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
index 00000000..8f123399
--- /dev/null
+++ b/src/locale/strxfrm.c
@@ -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
index 00000000..aa71779f
--- /dev/null
+++ b/src/locale/tmp
@@ -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
index 00000000..ba277919
--- /dev/null
+++ b/src/locale/tolower_l.c
@@ -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
index 00000000..73f2f39b
--- /dev/null
+++ b/src/locale/toupper_l.c
@@ -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
index 00000000..cdbce1c2
--- /dev/null
+++ b/src/locale/wcscoll.c
@@ -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
index 00000000..5f76e5a7
--- /dev/null
+++ b/src/locale/wcsxfrm.c
@@ -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
index 00000000..58b0523f
--- /dev/null
+++ b/src/malloc/DESIGN
@@ -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
index 00000000..e3b3af31
--- /dev/null
+++ b/src/malloc/__brk.c
@@ -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
index 00000000..49b74c8e
--- /dev/null
+++ b/src/malloc/__simple_malloc.c
@@ -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
index 00000000..9d574562
--- /dev/null
+++ b/src/malloc/calloc.c
@@ -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
index 00000000..d9a30fe4
--- /dev/null
+++ b/src/malloc/malloc.c
@@ -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
index 00000000..61f456e4
--- /dev/null
+++ b/src/malloc/memalign.c
@@ -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
index 00000000..ef86260d
--- /dev/null
+++ b/src/malloc/posix_memalign.c
@@ -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
index 00000000..16051100
--- /dev/null
+++ b/src/math/__fpclassify.c
@@ -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
index 00000000..bf59d0d4
--- /dev/null
+++ b/src/math/__fpclassifyf.c
@@ -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
index 00000000..4f93bef1
--- /dev/null
+++ b/src/math/__fpclassifyl.c
@@ -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
index 00000000..e0236391
--- /dev/null
+++ b/src/math/e_acos.c
@@ -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
index 00000000..4c59781b
--- /dev/null
+++ b/src/math/e_acosf.c
@@ -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
index 00000000..8b454e75
--- /dev/null
+++ b/src/math/e_acosh.c
@@ -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
index 00000000..b7f1df69
--- /dev/null
+++ b/src/math/e_acoshf.c
@@ -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
index 00000000..4bf162a1
--- /dev/null
+++ b/src/math/e_asin.c
@@ -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
index 00000000..9c693970
--- /dev/null
+++ b/src/math/e_asinf.c
@@ -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
index 00000000..dd021164
--- /dev/null
+++ b/src/math/e_atan2.c
@@ -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
index 00000000..535e10a0
--- /dev/null
+++ b/src/math/e_atan2f.c
@@ -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
index 00000000..45f1c966
--- /dev/null
+++ b/src/math/e_atanh.c
@@ -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
index 00000000..7356cfc9
--- /dev/null
+++ b/src/math/e_atanhf.c
@@ -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
index 00000000..ad425bd3
--- /dev/null
+++ b/src/math/e_cosh.c
@@ -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
index 00000000..6db10885
--- /dev/null
+++ b/src/math/e_coshf.c
@@ -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
index 00000000..66107b95
--- /dev/null
+++ b/src/math/e_exp.c
@@ -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
index 00000000..99818edc
--- /dev/null
+++ b/src/math/e_expf.c
@@ -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
index 00000000..99afe489
--- /dev/null
+++ b/src/math/e_fmod.c
@@ -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
index 00000000..fe86cb04
--- /dev/null
+++ b/src/math/e_fmodf.c
@@ -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
index 00000000..e925adc3
--- /dev/null
+++ b/src/math/e_hypot.c
@@ -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
index 00000000..13773554
--- /dev/null
+++ b/src/math/e_hypotf.c
@@ -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
index 00000000..9eb0e444
--- /dev/null
+++ b/src/math/e_log.c
@@ -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
index 00000000..3be179f7
--- /dev/null
+++ b/src/math/e_log10.c
@@ -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
index 00000000..8fc5c5ca
--- /dev/null
+++ b/src/math/e_log10f.c
@@ -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
index 00000000..46a8b8ce
--- /dev/null
+++ b/src/math/e_logf.c
@@ -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
index 00000000..aad24287
--- /dev/null
+++ b/src/math/e_pow.c
@@ -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
index 00000000..ae61c246
--- /dev/null
+++ b/src/math/e_powf.c
@@ -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
index 00000000..9eee36ae
--- /dev/null
+++ b/src/math/e_rem_pio2.c
@@ -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
index 00000000..4992ea0c
--- /dev/null
+++ b/src/math/e_rem_pio2f.c
@@ -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
index 00000000..9cb56919
--- /dev/null
+++ b/src/math/e_remainder.c
@@ -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
index 00000000..c292367d
--- /dev/null
+++ b/src/math/e_remainderf.c
@@ -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
index 00000000..cee2b44f
--- /dev/null
+++ b/src/math/e_scalb.c
@@ -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
index 00000000..de7d7f67
--- /dev/null
+++ b/src/math/e_scalbf.c
@@ -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
index 00000000..3a574274
--- /dev/null
+++ b/src/math/e_sinh.c
@@ -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
index 00000000..fe60608a
--- /dev/null
+++ b/src/math/e_sinhf.c
@@ -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
index 00000000..2bc68747
--- /dev/null
+++ b/src/math/e_sqrt.c
@@ -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
index 00000000..03a15beb
--- /dev/null
+++ b/src/math/e_sqrtf.c
@@ -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
index 00000000..d6c54a30
--- /dev/null
+++ b/src/math/i386/e_exp.s
@@ -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
index 00000000..8b137891
--- /dev/null
+++ b/src/math/i386/e_expf.s
@@ -0,0 +1 @@
+
diff --git a/src/math/i386/e_log.s b/src/math/i386/e_log.s
new file mode 100644
index 00000000..34b8d38d
--- /dev/null
+++ b/src/math/i386/e_log.s
@@ -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
index 00000000..7f48941b
--- /dev/null
+++ b/src/math/i386/e_log10.s
@@ -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
index 00000000..311486ea
--- /dev/null
+++ b/src/math/i386/e_log10f.s
@@ -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
index 00000000..b8beec0f
--- /dev/null
+++ b/src/math/i386/e_logf.s
@@ -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
index 00000000..b7ff3ef8
--- /dev/null
+++ b/src/math/i386/e_remainder.s
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/e_remainderf.s
diff --git a/src/math/i386/e_sqrt.s b/src/math/i386/e_sqrt.s
new file mode 100644
index 00000000..11314dca
--- /dev/null
+++ b/src/math/i386/e_sqrt.s
@@ -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
index 00000000..015e24cd
--- /dev/null
+++ b/src/math/i386/e_sqrtf.s
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_ceil.s
diff --git a/src/math/i386/s_ceilf.s b/src/math/i386/s_ceilf.s
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_ceilf.s
diff --git a/src/math/i386/s_fabs.s b/src/math/i386/s_fabs.s
new file mode 100644
index 00000000..10c70f37
--- /dev/null
+++ b/src/math/i386/s_fabs.s
@@ -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
index 00000000..45442699
--- /dev/null
+++ b/src/math/i386/s_fabsf.s
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_floor.s
diff --git a/src/math/i386/s_floorf.s b/src/math/i386/s_floorf.s
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_floorf.s
diff --git a/src/math/i386/s_ldexp.s b/src/math/i386/s_ldexp.s
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_ldexp.s
diff --git a/src/math/i386/s_ldexpf.s b/src/math/i386/s_ldexpf.s
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_ldexpf.s
diff --git a/src/math/i386/s_rint.s b/src/math/i386/s_rint.s
new file mode 100644
index 00000000..5ba4ab4a
--- /dev/null
+++ b/src/math/i386/s_rint.s
@@ -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
index 00000000..d7aacd8f
--- /dev/null
+++ b/src/math/i386/s_rintf.s
@@ -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
index 00000000..bd022b46
--- /dev/null
+++ b/src/math/i386/s_scalbln.s
@@ -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
index 00000000..379ec919
--- /dev/null
+++ b/src/math/i386/s_scalblnf.s
@@ -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
index 00000000..0773891a
--- /dev/null
+++ b/src/math/i386/s_trunc.s
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/src/math/i386/s_truncf.s
diff --git a/src/math/k_cos.c b/src/math/k_cos.c
new file mode 100644
index 00000000..22e9841e
--- /dev/null
+++ b/src/math/k_cos.c
@@ -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
index 00000000..61dc3749
--- /dev/null
+++ b/src/math/k_cosf.c
@@ -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
index 00000000..d993e4f2
--- /dev/null
+++ b/src/math/k_rem_pio2.c
@@ -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
index 00000000..b543f084
--- /dev/null
+++ b/src/math/k_rem_pio2f.c
@@ -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
index 00000000..9def2589
--- /dev/null
+++ b/src/math/k_sin.c
@@ -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
index 00000000..617f6148
--- /dev/null
+++ b/src/math/k_sinf.c
@@ -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
index 00000000..f721ae6d
--- /dev/null
+++ b/src/math/k_tan.c
@@ -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
index 00000000..99ede58c
--- /dev/null
+++ b/src/math/k_tanf.c
@@ -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
index 00000000..28a6a195
--- /dev/null
+++ b/src/math/math_private.h
@@ -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
index 00000000..26016091
--- /dev/null
+++ b/src/math/s_asinh.c
@@ -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
index 00000000..04f8d072
--- /dev/null
+++ b/src/math/s_asinhf.c
@@ -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
index 00000000..1faac024
--- /dev/null
+++ b/src/math/s_atan.c
@@ -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
index 00000000..03067e18
--- /dev/null
+++ b/src/math/s_atanf.c
@@ -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
index 00000000..8adcb191
--- /dev/null
+++ b/src/math/s_cbrt.c
@@ -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
index 00000000..e7b46de7
--- /dev/null
+++ b/src/math/s_cbrtf.c
@@ -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
index 00000000..1670cade
--- /dev/null
+++ b/src/math/s_ceil.c
@@ -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
index 00000000..3615041f
--- /dev/null
+++ b/src/math/s_ceilf.c
@@ -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
index 00000000..59d3877c
--- /dev/null
+++ b/src/math/s_copysign.c
@@ -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
index 00000000..d650e8e5
--- /dev/null
+++ b/src/math/s_copysignf.c
@@ -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
index 00000000..1893ab13
--- /dev/null
+++ b/src/math/s_cos.c
@@ -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
index 00000000..14b8e98b
--- /dev/null
+++ b/src/math/s_cosf.c
@@ -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
index 00000000..e321feea
--- /dev/null
+++ b/src/math/s_erf.c
@@ -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
index 00000000..28e2f7b3
--- /dev/null
+++ b/src/math/s_erff.c
@@ -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
index 00000000..6f1f6675
--- /dev/null
+++ b/src/math/s_expm1.c
@@ -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
index 00000000..b22cf0f9
--- /dev/null
+++ b/src/math/s_expm1f.c
@@ -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
index 00000000..74433250
--- /dev/null
+++ b/src/math/s_fabs.c
@@ -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
index 00000000..655d57d8
--- /dev/null
+++ b/src/math/s_fabsf.c
@@ -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
index 00000000..273cf6f4
--- /dev/null
+++ b/src/math/s_floor.c
@@ -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
index 00000000..1164decc
--- /dev/null
+++ b/src/math/s_floorf.c
@@ -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
index 00000000..f1ac498a
--- /dev/null
+++ b/src/math/s_ilogb.c
@@ -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
index 00000000..30359fef
--- /dev/null
+++ b/src/math/s_ilogbf.c
@@ -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
index 00000000..f4d1cd6a
--- /dev/null
+++ b/src/math/s_ldexp.c
@@ -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
index 00000000..3bad5f39
--- /dev/null
+++ b/src/math/s_ldexpf.c
@@ -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
index 00000000..2b1e00d0
--- /dev/null
+++ b/src/math/s_llrint.c
@@ -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
index 00000000..886d5ab1
--- /dev/null
+++ b/src/math/s_log1p.c
@@ -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
index 00000000..dcdd6bb3
--- /dev/null
+++ b/src/math/s_log1pf.c
@@ -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
index 00000000..be399c77
--- /dev/null
+++ b/src/math/s_logb.c
@@ -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
index 00000000..747664d3
--- /dev/null
+++ b/src/math/s_logbf.c
@@ -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
index 00000000..da8e1989
--- /dev/null
+++ b/src/math/s_lrint.c
@@ -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
index 00000000..d0b469b9
--- /dev/null
+++ b/src/math/s_lrintf.c
@@ -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
index 00000000..a5528d6b
--- /dev/null
+++ b/src/math/s_modf.c
@@ -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
index 00000000..de4dfd25
--- /dev/null
+++ b/src/math/s_modff.c
@@ -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
index 00000000..46d298ec
--- /dev/null
+++ b/src/math/s_nextafter.c
@@ -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
index 00000000..7ce08838
--- /dev/null
+++ b/src/math/s_nextafterf.c
@@ -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
index 00000000..1a2992d6
--- /dev/null
+++ b/src/math/s_remquo.c
@@ -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
index 00000000..be2a561a
--- /dev/null
+++ b/src/math/s_remquof.c
@@ -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
index 00000000..aec7d3c9
--- /dev/null
+++ b/src/math/s_rint.c
@@ -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
index 00000000..c441870d
--- /dev/null
+++ b/src/math/s_rintf.c
@@ -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
index 00000000..d5bea7a9
--- /dev/null
+++ b/src/math/s_round.c
@@ -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
index 00000000..c4fc3e19
--- /dev/null
+++ b/src/math/s_roundf.c
@@ -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
index 00000000..12b9391b
--- /dev/null
+++ b/src/math/s_scalbln.c
@@ -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
index 00000000..21e7641c
--- /dev/null
+++ b/src/math/s_scalblnf.c
@@ -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
index 00000000..2a2774ed
--- /dev/null
+++ b/src/math/s_sin.c
@@ -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
index 00000000..d2b8e806
--- /dev/null
+++ b/src/math/s_sinf.c
@@ -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
index 00000000..3333cb3d
--- /dev/null
+++ b/src/math/s_tan.c
@@ -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
index 00000000..660dd9c3
--- /dev/null
+++ b/src/math/s_tanf.c
@@ -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
index 00000000..78b8e849
--- /dev/null
+++ b/src/math/s_tanh.c
@@ -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
index 00000000..a0820409
--- /dev/null
+++ b/src/math/s_tanhf.c
@@ -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
index 00000000..02c65567
--- /dev/null
+++ b/src/math/s_trunc.c
@@ -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
index 00000000..c253e62b
--- /dev/null
+++ b/src/math/s_truncf.c
@@ -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
index 00000000..c87e00cd
--- /dev/null
+++ b/src/misc/basename.c
@@ -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
index 00000000..a2418ca9
--- /dev/null
+++ b/src/misc/bswap_32.c
@@ -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
index 00000000..961300b5
--- /dev/null
+++ b/src/misc/bswap_64.c
@@ -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
index 00000000..42918ef0
--- /dev/null
+++ b/src/misc/crypt.c
@@ -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
index 00000000..8ad0b9f3
--- /dev/null
+++ b/src/misc/cuserid.c
@@ -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
index 00000000..8f70dbb1
--- /dev/null
+++ b/src/misc/dirname.c
@@ -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
index 00000000..2f7cb321
--- /dev/null
+++ b/src/misc/ffs.c
@@ -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
index 00000000..de01e39c
--- /dev/null
+++ b/src/misc/ftw.c
@@ -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
index 00000000..7eb113d7
--- /dev/null
+++ b/src/misc/getdomainname.c
@@ -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
index 00000000..88f273d7
--- /dev/null
+++ b/src/misc/getgrouplist.c
@@ -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
index 00000000..abf0e847
--- /dev/null
+++ b/src/misc/getopt.c
@@ -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
index 00000000..2fb26b2b
--- /dev/null
+++ b/src/misc/getpriority.c
@@ -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
index 00000000..db25943b
--- /dev/null
+++ b/src/misc/getrlimit.c
@@ -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
index 00000000..1b8850f9
--- /dev/null
+++ b/src/misc/getrusage.c
@@ -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
index 00000000..dac9bf9e
--- /dev/null
+++ b/src/misc/getsubopt.c
@@ -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
index 00000000..808b7c9c
--- /dev/null
+++ b/src/misc/ioctl.c
@@ -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
index 00000000..d8f82efd
--- /dev/null
+++ b/src/misc/lockf.c
@@ -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
index 00000000..1b94ac15
--- /dev/null
+++ b/src/misc/nftw.c
@@ -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
index 00000000..0b4eb221
--- /dev/null
+++ b/src/misc/openpty.c
@@ -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
index 00000000..0d25a836
--- /dev/null
+++ b/src/misc/pty.c
@@ -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
index 00000000..f6b55495
--- /dev/null
+++ b/src/misc/realpath.c
@@ -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
index 00000000..8a68519e
--- /dev/null
+++ b/src/misc/sched_yield.c
@@ -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
index 00000000..26da4b83
--- /dev/null
+++ b/src/misc/setpriority.c
@@ -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
index 00000000..7fdfc4e5
--- /dev/null
+++ b/src/misc/setrlimit.c
@@ -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
index 00000000..4809d2da
--- /dev/null
+++ b/src/misc/syslog.c
@@ -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
index 00000000..fbe86643
--- /dev/null
+++ b/src/misc/uname.c
@@ -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
index 00000000..f03647ca
--- /dev/null
+++ b/src/mman/madvise.c
@@ -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
index 00000000..3c7c653c
--- /dev/null
+++ b/src/mman/mlock.c
@@ -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
index 00000000..782fc9db
--- /dev/null
+++ b/src/mman/mlockall.c
@@ -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
index 00000000..93c76582
--- /dev/null
+++ b/src/mman/mmap.c
@@ -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
index 00000000..11d5e231
--- /dev/null
+++ b/src/mman/mprotect.c
@@ -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
index 00000000..78491ef4
--- /dev/null
+++ b/src/mman/mremap.c
@@ -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
index 00000000..e0926470
--- /dev/null
+++ b/src/mman/msync.c
@@ -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
index 00000000..0db59815
--- /dev/null
+++ b/src/mman/munlock.c
@@ -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
index 00000000..ce3e86cc
--- /dev/null
+++ b/src/mman/munlockall.c
@@ -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
index 00000000..c9661cda
--- /dev/null
+++ b/src/mman/munmap.c
@@ -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
index 00000000..4727ad75
--- /dev/null
+++ b/src/mman/posix_madvise.c
@@ -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
index 00000000..9d2c3b16
--- /dev/null
+++ b/src/multibyte/btowc.c
@@ -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
index 00000000..8d3d3c0b
--- /dev/null
+++ b/src/multibyte/decode.c
@@ -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
index 00000000..e9b938dd
--- /dev/null
+++ b/src/multibyte/internal.c
@@ -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
index 00000000..427519a2
--- /dev/null
+++ b/src/multibyte/internal.h
@@ -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
index 00000000..26d35649
--- /dev/null
+++ b/src/multibyte/mblen.c
@@ -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
index 00000000..c9a9f033
--- /dev/null
+++ b/src/multibyte/mbrlen.c
@@ -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
index 00000000..09badebe
--- /dev/null
+++ b/src/multibyte/mbrtowc.c
@@ -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
index 00000000..d307e5a7
--- /dev/null
+++ b/src/multibyte/mbsinit.c
@@ -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
index 00000000..c6f0207f
--- /dev/null
+++ b/src/multibyte/mbsnrtowcs.c
@@ -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
index 00000000..e2b43480
--- /dev/null
+++ b/src/multibyte/mbsrtowcs.c
@@ -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
index 00000000..23e1d925
--- /dev/null
+++ b/src/multibyte/mbstowcs.c
@@ -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
index 00000000..bdcaeb3c
--- /dev/null
+++ b/src/multibyte/mbtowc.c
@@ -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
index 00000000..36180c8f
--- /dev/null
+++ b/src/multibyte/wcrtomb.c
@@ -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
index 00000000..666f6f3f
--- /dev/null
+++ b/src/multibyte/wcsnrtombs.c
@@ -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
index 00000000..3c48d65b
--- /dev/null
+++ b/src/multibyte/wcsrtombs.c
@@ -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
index 00000000..b9c1b18a
--- /dev/null
+++ b/src/multibyte/wcstombs.c
@@ -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
index 00000000..d6353ee1
--- /dev/null
+++ b/src/multibyte/wctob.c
@@ -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
index 00000000..6910ef37
--- /dev/null
+++ b/src/multibyte/wctomb.c
@@ -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
index 00000000..73ec422d
--- /dev/null
+++ b/src/network/__dns.c
@@ -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
index 00000000..9a3f7402
--- /dev/null
+++ b/src/network/__dns.h
@@ -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
index 00000000..ca9e5890
--- /dev/null
+++ b/src/network/__ipparse.c
@@ -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
index 00000000..83704096
--- /dev/null
+++ b/src/network/accept.c
@@ -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
index 00000000..3bef382c
--- /dev/null
+++ b/src/network/bind.c
@@ -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
index 00000000..6074122e
--- /dev/null
+++ b/src/network/connect.c
@@ -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
index 00000000..01b449bb
--- /dev/null
+++ b/src/network/dn_expand.c
@@ -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
index 00000000..4c2f24b5
--- /dev/null
+++ b/src/network/ent.c
@@ -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
index 00000000..df3798ae
--- /dev/null
+++ b/src/network/freeaddrinfo.c
@@ -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
index 00000000..ea00bed7
--- /dev/null
+++ b/src/network/gai_strerror.c
@@ -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
index 00000000..90e85f6a
--- /dev/null
+++ b/src/network/getaddrinfo.c
@@ -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
index 00000000..51e1c569
--- /dev/null
+++ b/src/network/gethostbyaddr.c
@@ -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
index 00000000..cdb1d503
--- /dev/null
+++ b/src/network/gethostbyaddr_r.c
@@ -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
index 00000000..5088a51e
--- /dev/null
+++ b/src/network/gethostbyname.c
@@ -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
index 00000000..9fbe2647
--- /dev/null
+++ b/src/network/gethostbyname2.c
@@ -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
index 00000000..c2ed75b4
--- /dev/null
+++ b/src/network/gethostbyname2_r.c
@@ -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
index 00000000..cd872541
--- /dev/null
+++ b/src/network/gethostbyname_r.c
@@ -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
index 00000000..0763ca88
--- /dev/null
+++ b/src/network/getnameinfo.c
@@ -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
index 00000000..7ecbe375
--- /dev/null
+++ b/src/network/getpeername.c
@@ -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
index 00000000..0b00ce11
--- /dev/null
+++ b/src/network/getservbyname.c
@@ -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
index 00000000..5c025150
--- /dev/null
+++ b/src/network/getservbyname_r.c
@@ -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
index 00000000..c9ecbb11
--- /dev/null
+++ b/src/network/getservbyport.c
@@ -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
index 00000000..004a6168
--- /dev/null
+++ b/src/network/getservbyport_r.c
@@ -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
index 00000000..4b1002f8
--- /dev/null
+++ b/src/network/getsockname.c
@@ -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
index 00000000..8c818863
--- /dev/null
+++ b/src/network/getsockopt.c
@@ -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
index 00000000..73ead046
--- /dev/null
+++ b/src/network/h_errno.c
@@ -0,0 +1 @@
+int h_errno;
diff --git a/src/network/hstrerror.c b/src/network/hstrerror.c
new file mode 100644
index 00000000..b7a6ab6c
--- /dev/null
+++ b/src/network/hstrerror.c
@@ -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
index 00000000..b21dace0
--- /dev/null
+++ b/src/network/htonl.c
@@ -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
index 00000000..522504a5
--- /dev/null
+++ b/src/network/htons.c
@@ -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
index 00000000..995387fa
--- /dev/null
+++ b/src/network/in6addr_any.c
@@ -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
index 00000000..b96005b8
--- /dev/null
+++ b/src/network/in6addr_loopback.c
@@ -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
index 00000000..84137281
--- /dev/null
+++ b/src/network/inet_addr.c
@@ -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
index 00000000..ea4ee165
--- /dev/null
+++ b/src/network/inet_aton.c
@@ -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
index 00000000..71411e0b
--- /dev/null
+++ b/src/network/inet_ntoa.c
@@ -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
index 00000000..3e8a6db0
--- /dev/null
+++ b/src/network/inet_ntop.c
@@ -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
index 00000000..349c4025
--- /dev/null
+++ b/src/network/inet_pton.c
@@ -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
index 00000000..7c8c1a8a
--- /dev/null
+++ b/src/network/listen.c
@@ -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
index 00000000..64379196
--- /dev/null
+++ b/src/network/ntohl.c
@@ -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
index 00000000..3544a479
--- /dev/null
+++ b/src/network/ntohs.c
@@ -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
index 00000000..8c25c53a
--- /dev/null
+++ b/src/network/proto.c
@@ -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
index 00000000..521a4b19
--- /dev/null
+++ b/src/network/recv.c
@@ -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
index 00000000..df50114b
--- /dev/null
+++ b/src/network/recvfrom.c
@@ -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
index 00000000..ead16f9c
--- /dev/null
+++ b/src/network/recvmsg.c
@@ -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
index 00000000..cbd5b155
--- /dev/null
+++ b/src/network/res_init.c
@@ -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
index 00000000..4ebeb102
--- /dev/null
+++ b/src/network/res_query.c
@@ -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
index 00000000..d72fb03c
--- /dev/null
+++ b/src/network/send.c
@@ -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
index 00000000..ea2fe482
--- /dev/null
+++ b/src/network/sendmsg.c
@@ -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
index 00000000..5d224b0b
--- /dev/null
+++ b/src/network/sendto.c
@@ -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
index 00000000..5ade6ad1
--- /dev/null
+++ b/src/network/serv.c
@@ -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
index 00000000..b50303b8
--- /dev/null
+++ b/src/network/setsockopt.c
@@ -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
index 00000000..91950c8a
--- /dev/null
+++ b/src/network/shutdown.c
@@ -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
index 00000000..5328a855
--- /dev/null
+++ b/src/network/sockatmark.c
@@ -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
index 00000000..afaeb411
--- /dev/null
+++ b/src/network/socket.c
@@ -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
index 00000000..9ae98587
--- /dev/null
+++ b/src/network/socketcall.h
@@ -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
index 00000000..65a47fd9
--- /dev/null
+++ b/src/network/socketpair.c
@@ -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
index 00000000..5b1333e3
--- /dev/null
+++ b/src/passwd/getgr_r.c
@@ -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
index 00000000..e9d25eba
--- /dev/null
+++ b/src/passwd/getgrent.c
@@ -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
index 00000000..ccb51d52
--- /dev/null
+++ b/src/passwd/getgrent_a.c
@@ -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
index 00000000..7b331e8a
--- /dev/null
+++ b/src/passwd/getpw_r.c
@@ -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
index 00000000..dabd411a
--- /dev/null
+++ b/src/passwd/getpwent.c
@@ -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
index 00000000..aaf84edd
--- /dev/null
+++ b/src/passwd/getpwent_a.c
@@ -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
index 00000000..8574a480
--- /dev/null
+++ b/src/passwd/getspent.c
@@ -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
index 00000000..041f8965
--- /dev/null
+++ b/src/passwd/getspnam.c
@@ -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
index 00000000..1dd39ce0
--- /dev/null
+++ b/src/passwd/getspnam_r.c
@@ -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
index 00000000..2feda617
--- /dev/null
+++ b/src/passwd/lckpwdf.c
@@ -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
index 00000000..0a76ef80
--- /dev/null
+++ b/src/passwd/pwf.h
@@ -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
index 00000000..755b4f2f
--- /dev/null
+++ b/src/prng/__rand48_step.c
@@ -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
index 00000000..05a4539e
--- /dev/null
+++ b/src/prng/__seed48.c
@@ -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
index 00000000..d808353c
--- /dev/null
+++ b/src/prng/drand48.c
@@ -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
index 00000000..32b27d42
--- /dev/null
+++ b/src/prng/lcong48.c
@@ -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
index 00000000..a3c4e4e2
--- /dev/null
+++ b/src/prng/lrand48.c
@@ -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
index 00000000..ee650fc3
--- /dev/null
+++ b/src/prng/mrand48.c
@@ -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
index 00000000..e3ce6347
--- /dev/null
+++ b/src/prng/rand.c
@@ -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
index 00000000..e96cfba9
--- /dev/null
+++ b/src/prng/rand_r.c
@@ -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
index 00000000..e6b7fd1f
--- /dev/null
+++ b/src/prng/random.c
@@ -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
index 00000000..e0699c09
--- /dev/null
+++ b/src/prng/seed48.c
@@ -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
index 00000000..0a56f6a0
--- /dev/null
+++ b/src/prng/srand48.c
@@ -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
index 00000000..77f4dcbd
--- /dev/null
+++ b/src/prng/srandom.c
@@ -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
index 00000000..4c6eaa94
--- /dev/null
+++ b/src/process/execl.c
@@ -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
index 00000000..37f629d9
--- /dev/null
+++ b/src/process/execle.c
@@ -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
index 00000000..33fb0f7f
--- /dev/null
+++ b/src/process/execlp.c
@@ -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
index 00000000..2ac0dec0
--- /dev/null
+++ b/src/process/execv.c
@@ -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
index 00000000..2a0b62d6
--- /dev/null
+++ b/src/process/execve.c
@@ -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
index 00000000..d799ddae
--- /dev/null
+++ b/src/process/execvp.c
@@ -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
index 00000000..1213f0f5
--- /dev/null
+++ b/src/process/fork.c
@@ -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
index 00000000..0f1c07b5
--- /dev/null
+++ b/src/process/system.c
@@ -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
index 00000000..32a7a6ed
--- /dev/null
+++ b/src/process/vfork.c
@@ -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
index 00000000..34da102d
--- /dev/null
+++ b/src/process/wait.c
@@ -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
index 00000000..0ec0d55c
--- /dev/null
+++ b/src/process/waitid.c
@@ -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
index 00000000..0ddcd15a
--- /dev/null
+++ b/src/process/waitpid.c
@@ -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
index 00000000..5f2fccdb
--- /dev/null
+++ b/src/regex/fnmatch.c
@@ -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
index 00000000..9a70f0bc
--- /dev/null
+++ b/src/regex/glob.c
@@ -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
index 00000000..3307942e
--- /dev/null
+++ b/src/regex/regcomp.c
@@ -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
index 00000000..39d70b2a
--- /dev/null
+++ b/src/regex/regerror.c
@@ -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
index 00000000..0c3d2834
--- /dev/null
+++ b/src/regex/regexec.c
@@ -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
index 00000000..d7bdd3db
--- /dev/null
+++ b/src/regex/tre-mem.c
@@ -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
index 00000000..bfd171f4
--- /dev/null
+++ b/src/regex/tre.h
@@ -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
index 00000000..e92943e1
--- /dev/null
+++ b/src/select/poll.c
@@ -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
index 00000000..795c5b0d
--- /dev/null
+++ b/src/select/pselect.c
@@ -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
index 00000000..a604d094
--- /dev/null
+++ b/src/select/select.c
@@ -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
index 00000000..c1a956c3
--- /dev/null
+++ b/src/setjmp/i386/longjmp.s
@@ -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
index 00000000..6c078b10
--- /dev/null
+++ b/src/setjmp/i386/setjmp.s
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/src/setjmp/longjmp.c
diff --git a/src/setjmp/setjmp.c b/src/setjmp/setjmp.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/setjmp/setjmp.c
diff --git a/src/signal/bsd_signal.c b/src/signal/bsd_signal.c
new file mode 100644
index 00000000..0b9a6855
--- /dev/null
+++ b/src/signal/bsd_signal.c
@@ -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
index 00000000..222d113e
--- /dev/null
+++ b/src/signal/getitimer.c
@@ -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
index 00000000..0e7eefb0
--- /dev/null
+++ b/src/signal/i386/sigsetjmp.s
@@ -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
index 00000000..cc4b51e1
--- /dev/null
+++ b/src/signal/kill.c
@@ -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
index 00000000..315ed447
--- /dev/null
+++ b/src/signal/killpg.c
@@ -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
index 00000000..52f8b428
--- /dev/null
+++ b/src/signal/raise.c
@@ -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
index 00000000..cacab036
--- /dev/null
+++ b/src/signal/setitimer.c
@@ -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
index 00000000..4acd1730
--- /dev/null
+++ b/src/signal/sigaction.c
@@ -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
index 00000000..23e655db
--- /dev/null
+++ b/src/signal/sigaddset.c
@@ -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
index 00000000..3cc2d456
--- /dev/null
+++ b/src/signal/sigaltstack.c
@@ -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
index 00000000..14042fb8
--- /dev/null
+++ b/src/signal/sigdelset.c
@@ -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
index 00000000..91f77adf
--- /dev/null
+++ b/src/signal/sigemptyset.c
@@ -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
index 00000000..fab50a52
--- /dev/null
+++ b/src/signal/sigfillset.c
@@ -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
index 00000000..5b0f6b18
--- /dev/null
+++ b/src/signal/sighold.c
@@ -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
index 00000000..98dff61e
--- /dev/null
+++ b/src/signal/sigignore.c
@@ -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
index 00000000..60b34054
--- /dev/null
+++ b/src/signal/siginterrupt.c
@@ -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
index 00000000..afd29e52
--- /dev/null
+++ b/src/signal/sigismember.c
@@ -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
index 00000000..33ac30ea
--- /dev/null
+++ b/src/signal/siglongjmp.c
@@ -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
index 00000000..08902760
--- /dev/null
+++ b/src/signal/signal.c
@@ -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
index 00000000..263c00f5
--- /dev/null
+++ b/src/signal/sigpause.c
@@ -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
index 00000000..7deda256
--- /dev/null
+++ b/src/signal/sigpending.c
@@ -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
index 00000000..e89f8765
--- /dev/null
+++ b/src/signal/sigprocmask.c
@@ -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
index 00000000..ce3abf6c
--- /dev/null
+++ b/src/signal/sigqueue.c
@@ -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
index 00000000..b0b3024b
--- /dev/null
+++ b/src/signal/sigrelse.c
@@ -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
index 00000000..0ef29873
--- /dev/null
+++ b/src/signal/sigrtmax.c
@@ -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
index 00000000..7ad06d22
--- /dev/null
+++ b/src/signal/sigrtmin.c
@@ -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
index 00000000..1b6b38fd
--- /dev/null
+++ b/src/signal/sigset.c
@@ -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
index 00000000..a6667a27
--- /dev/null
+++ b/src/signal/sigsetjmp.c
@@ -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
index 00000000..1acdab06
--- /dev/null
+++ b/src/signal/sigsuspend.c
@@ -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
index 00000000..155185de
--- /dev/null
+++ b/src/signal/sigtimedwait.c
@@ -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
index 00000000..9569d6b0
--- /dev/null
+++ b/src/signal/sigwait.c
@@ -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
index 00000000..e79feb91
--- /dev/null
+++ b/src/signal/sigwaitinfo.c
@@ -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
index 00000000..cb310fec
--- /dev/null
+++ b/src/stat/chmod.c
@@ -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
index 00000000..91897383
--- /dev/null
+++ b/src/stat/fchmod.c
@@ -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
index 00000000..f4f22b2c
--- /dev/null
+++ b/src/stat/fchmodat.c
@@ -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
index 00000000..5f643301
--- /dev/null
+++ b/src/stat/fstat.c
@@ -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
index 00000000..22bc2934
--- /dev/null
+++ b/src/stat/fstatat.c
@@ -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
index 00000000..83bd7486
--- /dev/null
+++ b/src/stat/fstatvfs.c
@@ -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
index 00000000..afdb5538
--- /dev/null
+++ b/src/stat/lstat.c
@@ -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
index 00000000..8295cad5
--- /dev/null
+++ b/src/stat/mkdir.c
@@ -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
index 00000000..1fb38250
--- /dev/null
+++ b/src/stat/mkdirat.c
@@ -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
index 00000000..60efcf73
--- /dev/null
+++ b/src/stat/mkfifo.c
@@ -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
index 00000000..d3a1f970
--- /dev/null
+++ b/src/stat/mkfifoat.c
@@ -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
index 00000000..0123eeef
--- /dev/null
+++ b/src/stat/mknod.c
@@ -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
index 00000000..b5687e47
--- /dev/null
+++ b/src/stat/mknodat.c
@@ -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
index 00000000..67640cc1
--- /dev/null
+++ b/src/stat/stat.c
@@ -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
index 00000000..55a05d52
--- /dev/null
+++ b/src/stat/statvfs.c
@@ -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
index 00000000..49cb48a6
--- /dev/null
+++ b/src/stat/umask.c
@@ -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
index 00000000..e0b12a15
--- /dev/null
+++ b/src/stdio/__fclose_ca.c
@@ -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
index 00000000..6ad7c57d
--- /dev/null
+++ b/src/stdio/__fdopen.c
@@ -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
index 00000000..57d9b73c
--- /dev/null
+++ b/src/stdio/__fopen_rb_ca.c
@@ -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
index 00000000..a4334e23
--- /dev/null
+++ b/src/stdio/__fpending.c
@@ -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
index 00000000..7d9652c8
--- /dev/null
+++ b/src/stdio/__ofl.c
@@ -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
index 00000000..e35104de
--- /dev/null
+++ b/src/stdio/__overflow.c
@@ -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
index 00000000..185615d3
--- /dev/null
+++ b/src/stdio/__scanf.c
@@ -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
index 00000000..e549b979
--- /dev/null
+++ b/src/stdio/__scanf.h
@@ -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
index 00000000..24fef33f
--- /dev/null
+++ b/src/stdio/__stdio_close.c
@@ -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
index 00000000..ee7e1258
--- /dev/null
+++ b/src/stdio/__stdio_read.c
@@ -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
index 00000000..fdb9fe7f
--- /dev/null
+++ b/src/stdio/__stdio_seek.c
@@ -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
index 00000000..78545626
--- /dev/null
+++ b/src/stdio/__stdio_write.c
@@ -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
index 00000000..5a51d610
--- /dev/null
+++ b/src/stdio/__uflow.c
@@ -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
index 00000000..b769f4e4
--- /dev/null
+++ b/src/stdio/__underflow.c
@@ -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
index 00000000..79e59c2d
--- /dev/null
+++ b/src/stdio/asprintf.c
@@ -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
index 00000000..3bf94d30
--- /dev/null
+++ b/src/stdio/clearerr.c
@@ -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
index 00000000..fa28322f
--- /dev/null
+++ b/src/stdio/dprintf.c
@@ -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
index 00000000..26bc37e8
--- /dev/null
+++ b/src/stdio/fclose.c
@@ -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
index 00000000..f2b739b5
--- /dev/null
+++ b/src/stdio/feof.c
@@ -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
index 00000000..f535fbed
--- /dev/null
+++ b/src/stdio/ferror.c
@@ -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
index 00000000..cf3f5b0e
--- /dev/null
+++ b/src/stdio/fflush.c
@@ -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
index 00000000..3a7f1e30
--- /dev/null
+++ b/src/stdio/fgetc.c
@@ -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
index 00000000..5b663d1e
--- /dev/null
+++ b/src/stdio/fgetpos.c
@@ -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
index 00000000..7939303e
--- /dev/null
+++ b/src/stdio/fgets.c
@@ -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
index 00000000..c990545f
--- /dev/null
+++ b/src/stdio/fgetwc.c
@@ -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
index 00000000..2e76b565
--- /dev/null
+++ b/src/stdio/fgetws.c
@@ -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
index 00000000..9ffb26d5
--- /dev/null
+++ b/src/stdio/fileno.c
@@ -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
index 00000000..77a60746
--- /dev/null
+++ b/src/stdio/fmemopen.c
@@ -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
index 00000000..670cf5f3
--- /dev/null
+++ b/src/stdio/fopen.c
@@ -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
index 00000000..a220cc10
--- /dev/null
+++ b/src/stdio/fprintf.c
@@ -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
index 00000000..ec859385
--- /dev/null
+++ b/src/stdio/fputc.c
@@ -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
index 00000000..e6bdb204
--- /dev/null
+++ b/src/stdio/fputs.c
@@ -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
index 00000000..b48bb74d
--- /dev/null
+++ b/src/stdio/fputwc.c
@@ -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
index 00000000..9057853b
--- /dev/null
+++ b/src/stdio/fputws.c
@@ -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
index 00000000..0fa0b2aa
--- /dev/null
+++ b/src/stdio/fread.c
@@ -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
index 00000000..8d3af9fc
--- /dev/null
+++ b/src/stdio/freopen.c
@@ -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
index 00000000..51fc9b30
--- /dev/null
+++ b/src/stdio/fscanf.c
@@ -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
index 00000000..bfaad375
--- /dev/null
+++ b/src/stdio/fseek.c
@@ -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
index 00000000..5d76c8cd
--- /dev/null
+++ b/src/stdio/fsetpos.c
@@ -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
index 00000000..aa1f5381
--- /dev/null
+++ b/src/stdio/ftell.c
@@ -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
index 00000000..f4da47f6
--- /dev/null
+++ b/src/stdio/fwide.c
@@ -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
index 00000000..23974fe1
--- /dev/null
+++ b/src/stdio/fwrite.c
@@ -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
index 00000000..a6892cf6
--- /dev/null
+++ b/src/stdio/fwscanf.c
@@ -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
index 00000000..b739b0a5
--- /dev/null
+++ b/src/stdio/getc.c
@@ -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
index 00000000..629223ea
--- /dev/null
+++ b/src/stdio/getc_unlocked.c
@@ -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
index 00000000..c1012658
--- /dev/null
+++ b/src/stdio/getchar.c
@@ -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
index 00000000..299cb958
--- /dev/null
+++ b/src/stdio/getchar_unlocked.c
@@ -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
index 00000000..f770d20b
--- /dev/null
+++ b/src/stdio/getdelim.c
@@ -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
index 00000000..a3a6651b
--- /dev/null
+++ b/src/stdio/getline.c
@@ -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
index 00000000..24319eb2
--- /dev/null
+++ b/src/stdio/gets.c
@@ -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
index 00000000..de9e985a
--- /dev/null
+++ b/src/stdio/getw.c
@@ -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
index 00000000..a2818bc4
--- /dev/null
+++ b/src/stdio/getwc.c
@@ -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
index 00000000..2295bd40
--- /dev/null
+++ b/src/stdio/getwchar.c
@@ -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
index 00000000..c2fe7a24
--- /dev/null
+++ b/src/stdio/pclose.c
@@ -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
index 00000000..e4637c8a
--- /dev/null
+++ b/src/stdio/perror.c
@@ -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
index 00000000..1d33e9d6
--- /dev/null
+++ b/src/stdio/popen.c
@@ -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
index 00000000..efeb8b33
--- /dev/null
+++ b/src/stdio/printf.c
@@ -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
index 00000000..3c9dc11e
--- /dev/null
+++ b/src/stdio/putc.c
@@ -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
index 00000000..f01da717
--- /dev/null
+++ b/src/stdio/putc_unlocked.c
@@ -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
index 00000000..945636d5
--- /dev/null
+++ b/src/stdio/putchar.c
@@ -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
index 00000000..72d47d15
--- /dev/null
+++ b/src/stdio/putchar_unlocked.c
@@ -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
index 00000000..eb70efdc
--- /dev/null
+++ b/src/stdio/puts.c
@@ -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
index 00000000..137832ee
--- /dev/null
+++ b/src/stdio/putw.c
@@ -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
index 00000000..80b54a47
--- /dev/null
+++ b/src/stdio/putwc.c
@@ -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
index 00000000..3aacc1cf
--- /dev/null
+++ b/src/stdio/putwchar.c
@@ -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
index 00000000..8e338277
--- /dev/null
+++ b/src/stdio/remove.c
@@ -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
index 00000000..4eced08a
--- /dev/null
+++ b/src/stdio/rename.c
@@ -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
index 00000000..7944b434
--- /dev/null
+++ b/src/stdio/rewind.c
@@ -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
index 00000000..a04a4402
--- /dev/null
+++ b/src/stdio/scanf.c
@@ -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
index 00000000..205afcfe
--- /dev/null
+++ b/src/stdio/setbuf.c
@@ -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
index 00000000..2985d3f1
--- /dev/null
+++ b/src/stdio/setvbuf.c
@@ -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
index 00000000..4071c2f6
--- /dev/null
+++ b/src/stdio/snprintf.c
@@ -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
index 00000000..6b225409
--- /dev/null
+++ b/src/stdio/sprintf.c
@@ -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
index 00000000..a1cea699
--- /dev/null
+++ b/src/stdio/sscanf.c
@@ -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
index 00000000..4a79d4e7
--- /dev/null
+++ b/src/stdio/stderr.c
@@ -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
index 00000000..51c99232
--- /dev/null
+++ b/src/stdio/stdin.c
@@ -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
index 00000000..bf6eea6c
--- /dev/null
+++ b/src/stdio/stdout.c
@@ -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
index 00000000..b66ad03e
--- /dev/null
+++ b/src/stdio/swscanf.c
@@ -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
index 00000000..2cbcb864
--- /dev/null
+++ b/src/stdio/tempnam.c
@@ -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
index 00000000..185025f1
--- /dev/null
+++ b/src/stdio/tmpfile.c
@@ -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
index 00000000..14d59220
--- /dev/null
+++ b/src/stdio/tmpnam.c
@@ -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
index 00000000..07181684
--- /dev/null
+++ b/src/stdio/ungetc.c
@@ -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
index 00000000..f7cde2e0
--- /dev/null
+++ b/src/stdio/ungetwc.c
@@ -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
index 00000000..f2bbc7aa
--- /dev/null
+++ b/src/stdio/vasprintf.c
@@ -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
index 00000000..bfb1b0a9
--- /dev/null
+++ b/src/stdio/vdprintf.c
@@ -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
index 00000000..5e19acc5
--- /dev/null
+++ b/src/stdio/vfprintf.c
@@ -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
index 00000000..69f45081
--- /dev/null
+++ b/src/stdio/vfscanf.c
@@ -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
index 00000000..491c1403
--- /dev/null
+++ b/src/stdio/vfwscanf.c
@@ -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
index 00000000..67b38dac
--- /dev/null
+++ b/src/stdio/vprintf.c
@@ -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
index 00000000..6f55b1c3
--- /dev/null
+++ b/src/stdio/vscanf.c
@@ -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
index 00000000..bda6b49b
--- /dev/null
+++ b/src/stdio/vsnprintf.c
@@ -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
index 00000000..7836ccb2
--- /dev/null
+++ b/src/stdio/vsprintf.c
@@ -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
index 00000000..fd48f709
--- /dev/null
+++ b/src/stdio/vsscanf.c
@@ -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
index 00000000..2c4ffbe0
--- /dev/null
+++ b/src/stdio/vswscanf.c
@@ -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
index 00000000..86da0457
--- /dev/null
+++ b/src/stdio/vwscanf.c
@@ -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
index 00000000..34b58846
--- /dev/null
+++ b/src/stdio/wscanf.c
@@ -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
index 00000000..4806d629
--- /dev/null
+++ b/src/stdlib/abs.c
@@ -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
index 00000000..f7fcd826
--- /dev/null
+++ b/src/stdlib/atof.c
@@ -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
index 00000000..648b154f
--- /dev/null
+++ b/src/stdlib/atoi.c
@@ -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
index 00000000..9c91bba9
--- /dev/null
+++ b/src/stdlib/atol.c
@@ -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
index 00000000..0e03e0a1
--- /dev/null
+++ b/src/stdlib/atoll.c
@@ -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
index 00000000..61d89367
--- /dev/null
+++ b/src/stdlib/bsearch.c
@@ -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
index 00000000..e42c1f14
--- /dev/null
+++ b/src/stdlib/div.c
@@ -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
index 00000000..ae82cb30
--- /dev/null
+++ b/src/stdlib/frexp.c
@@ -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
index 00000000..ee5e910a
--- /dev/null
+++ b/src/stdlib/frexpf.c
@@ -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
index 00000000..ecfff007
--- /dev/null
+++ b/src/stdlib/frexpl.c
@@ -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
index 00000000..81001819
--- /dev/null
+++ b/src/stdlib/imaxabs.c
@@ -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
index 00000000..b2ce821f
--- /dev/null
+++ b/src/stdlib/imaxdiv.c
@@ -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
index 00000000..675b95b8
--- /dev/null
+++ b/src/stdlib/labs.c
@@ -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
index 00000000..36eb960b
--- /dev/null
+++ b/src/stdlib/ldiv.c
@@ -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
index 00000000..bec4a03d
--- /dev/null
+++ b/src/stdlib/llabs.c
@@ -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
index 00000000..7aaf7a0e
--- /dev/null
+++ b/src/stdlib/lldiv.c
@@ -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
index 00000000..f5bf3d02
--- /dev/null
+++ b/src/stdlib/qsort.c
@@ -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
index 00000000..388058fe
--- /dev/null
+++ b/src/stdlib/strtod.c
@@ -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
index 00000000..07b32df4
--- /dev/null
+++ b/src/stdlib/strtof.c
@@ -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
index 00000000..19691091
--- /dev/null
+++ b/src/stdlib/strtoimax.c
@@ -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
index 00000000..ace820af
--- /dev/null
+++ b/src/stdlib/strtol.c
@@ -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
index 00000000..54f80469
--- /dev/null
+++ b/src/stdlib/strtold.c
@@ -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
index 00000000..9ab66fd9
--- /dev/null
+++ b/src/stdlib/strtoll.c
@@ -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
index 00000000..951d5e8c
--- /dev/null
+++ b/src/stdlib/strtoul.c
@@ -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
index 00000000..20aa7bde
--- /dev/null
+++ b/src/stdlib/strtoull.c
@@ -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
index 00000000..a529f6e8
--- /dev/null
+++ b/src/stdlib/strtoumax.c
@@ -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
index 00000000..861fcb54
--- /dev/null
+++ b/src/stdlib/wcstoimax.c
@@ -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
index 00000000..aad62e5b
--- /dev/null
+++ b/src/stdlib/wcstol.c
@@ -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
index 00000000..ddfea74b
--- /dev/null
+++ b/src/stdlib/wcstoll.c
@@ -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
index 00000000..e39faafe
--- /dev/null
+++ b/src/stdlib/wcstoul.c
@@ -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
index 00000000..e324dfb2
--- /dev/null
+++ b/src/stdlib/wcstoull.c
@@ -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
index 00000000..a8f4680f
--- /dev/null
+++ b/src/stdlib/wcstoumax.c
@@ -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
index 00000000..5d6a388b
--- /dev/null
+++ b/src/string/bcmp.c
@@ -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
index 00000000..e76272fc
--- /dev/null
+++ b/src/string/bcopy.c
@@ -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
index 00000000..0f98b4a5
--- /dev/null
+++ b/src/string/bzero.c
@@ -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
index 00000000..dd611251
--- /dev/null
+++ b/src/string/index.c
@@ -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
index 00000000..a0472f78
--- /dev/null
+++ b/src/string/memchr.c
@@ -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
index 00000000..bdbce9f0
--- /dev/null
+++ b/src/string/memcmp.c
@@ -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
index 00000000..02cb4694
--- /dev/null
+++ b/src/string/memcpy.c
@@ -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
index 00000000..22bb4b35
--- /dev/null
+++ b/src/string/memmove.c
@@ -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
index 00000000..e54251cd
--- /dev/null
+++ b/src/string/mempcpy.c
@@ -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
index 00000000..20e47c45
--- /dev/null
+++ b/src/string/memset.c
@@ -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
index 00000000..17df2bf2
--- /dev/null
+++ b/src/string/rindex.c
@@ -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
index 00000000..10ca4933
--- /dev/null
+++ b/src/string/stpcpy.c
@@ -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
index 00000000..a877f5fe
--- /dev/null
+++ b/src/string/stpncpy.c
@@ -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
index 00000000..dd879052
--- /dev/null
+++ b/src/string/strcasecmp.c
@@ -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
index 00000000..f1cb0e84
--- /dev/null
+++ b/src/string/strcasestr.c
@@ -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
index 00000000..29fdb611
--- /dev/null
+++ b/src/string/strcat.c
@@ -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
index 00000000..e606f4fe
--- /dev/null
+++ b/src/string/strchr.c
@@ -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
index 00000000..5e0c1a1a
--- /dev/null
+++ b/src/string/strchrnul.c
@@ -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
index 00000000..91eb7404
--- /dev/null
+++ b/src/string/strcmp.c
@@ -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
index 00000000..7675e9ce
--- /dev/null
+++ b/src/string/strcpy.c
@@ -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
index 00000000..439b7be4
--- /dev/null
+++ b/src/string/strcspn.c
@@ -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
index 00000000..dd5f80c1
--- /dev/null
+++ b/src/string/strdup.c
@@ -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
index 00000000..6fdd4ce2
--- /dev/null
+++ b/src/string/strerror_r.c
@@ -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
index 00000000..a6b94c4c
--- /dev/null
+++ b/src/string/strlcat.c
@@ -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
index 00000000..bbebf1db
--- /dev/null
+++ b/src/string/strlcpy.c
@@ -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
index 00000000..936fb5cf
--- /dev/null
+++ b/src/string/strlen.c
@@ -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
index 00000000..4f9230e1
--- /dev/null
+++ b/src/string/strncasecmp.c
@@ -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
index 00000000..255b7a72
--- /dev/null
+++ b/src/string/strncat.c
@@ -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
index 00000000..52ba0323
--- /dev/null
+++ b/src/string/strncmp.c
@@ -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
index 00000000..c0cd7974
--- /dev/null
+++ b/src/string/strncpy.c
@@ -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
index 00000000..617d27ba
--- /dev/null
+++ b/src/string/strndup.c
@@ -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
index 00000000..6442eb79
--- /dev/null
+++ b/src/string/strnlen.c
@@ -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
index 00000000..55947c64
--- /dev/null
+++ b/src/string/strpbrk.c
@@ -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
index 00000000..31c8e0b8
--- /dev/null
+++ b/src/string/strrchr.c
@@ -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
index 00000000..1bfe1db1
--- /dev/null
+++ b/src/string/strsep.c
@@ -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
index 00000000..72fba8d1
--- /dev/null
+++ b/src/string/strsignal.c
@@ -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
index 00000000..59b063e5
--- /dev/null
+++ b/src/string/strspn.c
@@ -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
index 00000000..4d536a73
--- /dev/null
+++ b/src/string/strstr.c
@@ -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
index 00000000..1ba221cb
--- /dev/null
+++ b/src/string/strtok.c
@@ -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
index 00000000..c763897a
--- /dev/null
+++ b/src/string/strtok_r.c
@@ -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
index 00000000..b2132884
--- /dev/null
+++ b/src/string/swab.c
@@ -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
index 00000000..946f16e2
--- /dev/null
+++ b/src/string/wcscat.c
@@ -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
index 00000000..8dfc2f31
--- /dev/null
+++ b/src/string/wcschr.c
@@ -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
index 00000000..26eeee70
--- /dev/null
+++ b/src/string/wcscmp.c
@@ -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
index 00000000..e0ac194f
--- /dev/null
+++ b/src/string/wcscpy.c
@@ -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
index 00000000..c4e52722
--- /dev/null
+++ b/src/string/wcscspn.c
@@ -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
index 00000000..1b7b6655
--- /dev/null
+++ b/src/string/wcslen.c
@@ -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
index 00000000..b07abe45
--- /dev/null
+++ b/src/string/wcsncat.c
@@ -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
index 00000000..1b159f41
--- /dev/null
+++ b/src/string/wcsncmp.c
@@ -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
index 00000000..0164208d
--- /dev/null
+++ b/src/string/wcsncpy.c
@@ -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
index 00000000..0c72c197
--- /dev/null
+++ b/src/string/wcspbrk.c
@@ -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
index 00000000..7503475a
--- /dev/null
+++ b/src/string/wcsrchr.c
@@ -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
index 00000000..4320d8f6
--- /dev/null
+++ b/src/string/wcsspn.c
@@ -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
index 00000000..966174f8
--- /dev/null
+++ b/src/string/wcsstr.c
@@ -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
index 00000000..9cfe4ac4
--- /dev/null
+++ b/src/string/wcswcs.c
@@ -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
index 00000000..a3ee0e61
--- /dev/null
+++ b/src/string/wmemchr.c
@@ -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
index 00000000..6788a383
--- /dev/null
+++ b/src/string/wmemcmp.c
@@ -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
index 00000000..330e37c7
--- /dev/null
+++ b/src/string/wmemcpy.c
@@ -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
index 00000000..49608cae
--- /dev/null
+++ b/src/string/wmemmove.c
@@ -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
index 00000000..1a2a8618
--- /dev/null
+++ b/src/string/wmemset.c
@@ -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
index 00000000..32003969
--- /dev/null
+++ b/src/stub/utmpx.c
@@ -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
index 00000000..f8b067ec
--- /dev/null
+++ b/src/temp/mkdtemp.c
@@ -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
index 00000000..b1567191
--- /dev/null
+++ b/src/temp/mkstemp.c
@@ -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
index 00000000..8638e087
--- /dev/null
+++ b/src/temp/mktemp.c
@@ -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
index 00000000..0ebc198c
--- /dev/null
+++ b/src/termios/cfgetospeed.c
@@ -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
index 00000000..80c790f1
--- /dev/null
+++ b/src/termios/cfsetospeed.c
@@ -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
index 00000000..c51dd401
--- /dev/null
+++ b/src/termios/tcdrain.c
@@ -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
index 00000000..c7fc3fe2
--- /dev/null
+++ b/src/termios/tcflow.c
@@ -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
index 00000000..50222669
--- /dev/null
+++ b/src/termios/tcflush.c
@@ -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
index 00000000..d9ce786e
--- /dev/null
+++ b/src/termios/tcgetattr.c
@@ -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
index 00000000..1053fd64
--- /dev/null
+++ b/src/termios/tcgetsid.c
@@ -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
index 00000000..b6df0a23
--- /dev/null
+++ b/src/termios/tcsendbreak.c
@@ -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
index 00000000..e9a168f3
--- /dev/null
+++ b/src/termios/tcsetattr.c
@@ -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
index 00000000..93352fa3
--- /dev/null
+++ b/src/thread/__futex.c
@@ -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
index 00000000..557c6a62
--- /dev/null
+++ b/src/thread/__lock.c
@@ -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
index 00000000..576d8b40
--- /dev/null
+++ b/src/thread/__set_thread_area.c
@@ -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
index 00000000..354def2c
--- /dev/null
+++ b/src/thread/__timedwait.c
@@ -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
index 00000000..e69de29b
--- /dev/null
+++ b/src/thread/__unmapself.c
diff --git a/src/thread/__wait.c b/src/thread/__wait.c
new file mode 100644
index 00000000..8c249cd3
--- /dev/null
+++ b/src/thread/__wait.c
@@ -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
index 00000000..048ddcc0
--- /dev/null
+++ b/src/thread/__wake.c
@@ -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
index 00000000..e35ba824
--- /dev/null
+++ b/src/thread/cancellation.c
@@ -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
index 00000000..971bfeed
--- /dev/null
+++ b/src/thread/clone.c
@@ -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
index 00000000..5c674966
--- /dev/null
+++ b/src/thread/i386/__unmapself.s
@@ -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
index 00000000..4f33366c
--- /dev/null
+++ b/src/thread/i386/clone.s
@@ -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
index 00000000..b5845dd0
--- /dev/null
+++ b/src/thread/pthread_attr_destroy.c
@@ -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
index 00000000..9cd49536
--- /dev/null
+++ b/src/thread/pthread_attr_getdetachstate.c
@@ -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
index 00000000..3f089c8c
--- /dev/null
+++ b/src/thread/pthread_attr_getguardsize.c
@@ -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
index 00000000..0cb224d3
--- /dev/null
+++ b/src/thread/pthread_attr_getscope.c
@@ -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
index 00000000..40bbf186
--- /dev/null
+++ b/src/thread/pthread_attr_getstacksize.c
@@ -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
index 00000000..d91bf157
--- /dev/null
+++ b/src/thread/pthread_attr_init.c
@@ -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
index 00000000..d23b4778
--- /dev/null
+++ b/src/thread/pthread_attr_setdetachstate.c
@@ -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
index 00000000..e0e8d3fb
--- /dev/null
+++ b/src/thread/pthread_attr_setguardsize.c
@@ -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
index 00000000..a970a819
--- /dev/null
+++ b/src/thread/pthread_attr_setscope.c
@@ -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
index 00000000..58f4bb18
--- /dev/null
+++ b/src/thread/pthread_attr_setstacksize.c
@@ -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
index 00000000..2898c41a
--- /dev/null
+++ b/src/thread/pthread_barrier_destroy.c
@@ -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
index 00000000..2cc67ed5
--- /dev/null
+++ b/src/thread/pthread_barrier_init.c
@@ -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
index 00000000..02c252ad
--- /dev/null
+++ b/src/thread/pthread_barrier_wait.c
@@ -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
index 00000000..9397ffe9
--- /dev/null
+++ b/src/thread/pthread_cancel.c
@@ -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
index 00000000..7a023b85
--- /dev/null
+++ b/src/thread/pthread_cond_broadcast.c
@@ -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
index 00000000..1d21a5a8
--- /dev/null
+++ b/src/thread/pthread_cond_destroy.c
@@ -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
index 00000000..33948606
--- /dev/null
+++ b/src/thread/pthread_cond_init.c
@@ -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
index 00000000..0dd9416b
--- /dev/null
+++ b/src/thread/pthread_cond_signal.c
@@ -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
index 00000000..b67dded4
--- /dev/null
+++ b/src/thread/pthread_cond_timedwait.c
@@ -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
index 00000000..eb70e5f7
--- /dev/null
+++ b/src/thread/pthread_cond_wait.c
@@ -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
index 00000000..6fa484c7
--- /dev/null
+++ b/src/thread/pthread_create.c
@@ -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
index 00000000..f0eae3e8
--- /dev/null
+++ b/src/thread/pthread_detach.c
@@ -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
index 00000000..a55d280c
--- /dev/null
+++ b/src/thread/pthread_equal.c
@@ -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
index 00000000..4966e234
--- /dev/null
+++ b/src/thread/pthread_exit.c
@@ -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
index 00000000..a6ca27d0
--- /dev/null
+++ b/src/thread/pthread_getspecific.c
@@ -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
index 00000000..5210ed48
--- /dev/null
+++ b/src/thread/pthread_join.c
@@ -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
index 00000000..efc38046
--- /dev/null
+++ b/src/thread/pthread_key_create.c
@@ -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
index 00000000..4914ebb4
--- /dev/null
+++ b/src/thread/pthread_key_delete.c
@@ -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
index 00000000..9d85fa5b
--- /dev/null
+++ b/src/thread/pthread_kill.c
@@ -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
index 00000000..6d49e689
--- /dev/null
+++ b/src/thread/pthread_mutex_destroy.c
@@ -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
index 00000000..d453543d
--- /dev/null
+++ b/src/thread/pthread_mutex_init.c
@@ -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
index 00000000..6696f17a
--- /dev/null
+++ b/src/thread/pthread_mutex_lock.c
@@ -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
index 00000000..5dfad94f
--- /dev/null
+++ b/src/thread/pthread_mutex_timedlock.c
@@ -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
index 00000000..1e3817bb
--- /dev/null
+++ b/src/thread/pthread_mutex_trylock.c
@@ -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
index 00000000..23e64ac8
--- /dev/null
+++ b/src/thread/pthread_mutex_unlock.c
@@ -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
index 00000000..9fd69747
--- /dev/null
+++ b/src/thread/pthread_mutexattr_destroy.c
@@ -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
index 00000000..9edb16c6
--- /dev/null
+++ b/src/thread/pthread_mutexattr_gettype.c
@@ -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
index 00000000..ea631069
--- /dev/null
+++ b/src/thread/pthread_mutexattr_init.c
@@ -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
index 00000000..4e85950e
--- /dev/null
+++ b/src/thread/pthread_mutexattr_settype.c
@@ -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
index 00000000..72230054
--- /dev/null
+++ b/src/thread/pthread_once.c
@@ -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
index 00000000..49ecfbd0
--- /dev/null
+++ b/src/thread/pthread_rwlock_destroy.c
@@ -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
index 00000000..f87d566c
--- /dev/null
+++ b/src/thread/pthread_rwlock_init.c
@@ -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
index 00000000..6bcdb815
--- /dev/null
+++ b/src/thread/pthread_rwlock_rdlock.c
@@ -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
index 00000000..290327de
--- /dev/null
+++ b/src/thread/pthread_rwlock_timedrdlock.c
@@ -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
index 00000000..9f749648
--- /dev/null
+++ b/src/thread/pthread_rwlock_timedwrlock.c
@@ -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
index 00000000..f59fbbdd
--- /dev/null
+++ b/src/thread/pthread_rwlock_tryrdlock.c
@@ -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
index 00000000..c029b874
--- /dev/null
+++ b/src/thread/pthread_rwlock_trywrlock.c
@@ -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
index 00000000..f39117e7
--- /dev/null
+++ b/src/thread/pthread_rwlock_unlock.c
@@ -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
index 00000000..219e924a
--- /dev/null
+++ b/src/thread/pthread_rwlock_wrlock.c
@@ -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
index 00000000..686d73d5
--- /dev/null
+++ b/src/thread/pthread_self.c
@@ -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
index 00000000..23c38851
--- /dev/null
+++ b/src/thread/pthread_setcancelstate.c
@@ -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
index 00000000..c73db22f
--- /dev/null
+++ b/src/thread/pthread_setcanceltype.c
@@ -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
index 00000000..171cef41
--- /dev/null
+++ b/src/thread/pthread_setspecific.c
@@ -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
index 00000000..e65a820c
--- /dev/null
+++ b/src/thread/pthread_spin_destroy.c
@@ -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
index 00000000..681881cf
--- /dev/null
+++ b/src/thread/pthread_spin_init.c
@@ -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
index 00000000..59fa6ea8
--- /dev/null
+++ b/src/thread/pthread_spin_lock.c
@@ -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
index 00000000..c12696b3
--- /dev/null
+++ b/src/thread/pthread_spin_trylock.c
@@ -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
index 00000000..a7eab334
--- /dev/null
+++ b/src/thread/pthread_spin_unlock.c
@@ -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
index 00000000..774b7068
--- /dev/null
+++ b/src/thread/pthread_testcancel.c
@@ -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
index 00000000..18535802
--- /dev/null
+++ b/src/time/__asctime.c
@@ -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
index 00000000..967e5180
--- /dev/null
+++ b/src/time/__time.h
@@ -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
index 00000000..a1ebc452
--- /dev/null
+++ b/src/time/__time_to_tm.c
@@ -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
index 00000000..3fa15fad
--- /dev/null
+++ b/src/time/__tm_to_time.c
@@ -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
index 00000000..3102eb87
--- /dev/null
+++ b/src/time/asctime.c
@@ -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
index 00000000..e51b8804
--- /dev/null
+++ b/src/time/asctime_r.c
@@ -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
index 00000000..2feddb36
--- /dev/null
+++ b/src/time/clock.c
@@ -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
index 00000000..dab09d50
--- /dev/null
+++ b/src/time/clock_gettime.c
@@ -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
index 00000000..185ec554
--- /dev/null
+++ b/src/time/ctime.c
@@ -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
index 00000000..d2260a16
--- /dev/null
+++ b/src/time/ctime_r.c
@@ -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
index 00000000..80a18cc0
--- /dev/null
+++ b/src/time/difftime.c
@@ -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
index 00000000..2b8a287d
--- /dev/null
+++ b/src/time/gettimeofday.c
@@ -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
index 00000000..d4d5d1f1
--- /dev/null
+++ b/src/time/gmtime.c
@@ -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
index 00000000..5b565a65
--- /dev/null
+++ b/src/time/gmtime_r.c
@@ -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
index 00000000..abd5e84d
--- /dev/null
+++ b/src/time/localtime.c
@@ -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
index 00000000..2bf10378
--- /dev/null
+++ b/src/time/localtime_r.c
@@ -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
index 00000000..858cd50d
--- /dev/null
+++ b/src/time/mktime.c
@@ -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
index 00000000..5ac4c359
--- /dev/null
+++ b/src/time/nanosleep.c
@@ -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
index 00000000..f1b94631
--- /dev/null
+++ b/src/time/strftime.c
@@ -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
index 00000000..db72e610
--- /dev/null
+++ b/src/time/strptime.c
@@ -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
index 00000000..3457dade
--- /dev/null
+++ b/src/time/time.c
@@ -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
index 00000000..e9b5a823
--- /dev/null
+++ b/src/time/times.c
@@ -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
index 00000000..4e167b0b
--- /dev/null
+++ b/src/time/timezone.s
@@ -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
index 00000000..6d69957e
--- /dev/null
+++ b/src/time/tzset.c
@@ -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
index 00000000..56e9e13a
--- /dev/null
+++ b/src/time/utime.c
@@ -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
index 00000000..d2e84c4c
--- /dev/null
+++ b/src/unistd/_exit.c
@@ -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
index 00000000..2c10e58c
--- /dev/null
+++ b/src/unistd/access.c
@@ -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
index 00000000..bba444d8
--- /dev/null
+++ b/src/unistd/alarm.c
@@ -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
index 00000000..c89bda38
--- /dev/null
+++ b/src/unistd/chdir.c
@@ -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
index 00000000..6069a2fe
--- /dev/null
+++ b/src/unistd/chown.c
@@ -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
index 00000000..97302f67
--- /dev/null
+++ b/src/unistd/close.c
@@ -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
index 00000000..4332f726
--- /dev/null
+++ b/src/unistd/confstr.c
@@ -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
index 00000000..21b44ec8
--- /dev/null
+++ b/src/unistd/ctermid.c
@@ -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
index 00000000..b11cd715
--- /dev/null
+++ b/src/unistd/dup.c
@@ -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
index 00000000..93325446
--- /dev/null
+++ b/src/unistd/dup2.c
@@ -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
index 00000000..99a93785
--- /dev/null
+++ b/src/unistd/faccessat.c
@@ -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
index 00000000..b2acbc29
--- /dev/null
+++ b/src/unistd/fchdir.c
@@ -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
index 00000000..990f006d
--- /dev/null
+++ b/src/unistd/fchown.c
@@ -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
index 00000000..70626428
--- /dev/null
+++ b/src/unistd/fchownat.c
@@ -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
index 00000000..ef7c9a9d
--- /dev/null
+++ b/src/unistd/fdatasync.c
@@ -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
index 00000000..7cfedc98
--- /dev/null
+++ b/src/unistd/fsync.c
@@ -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
index 00000000..e0b2f4bb
--- /dev/null
+++ b/src/unistd/ftruncate.c
@@ -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
index 00000000..4910f42c
--- /dev/null
+++ b/src/unistd/getcwd.c
@@ -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
index 00000000..0e626b75
--- /dev/null
+++ b/src/unistd/getegid.c
@@ -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
index 00000000..39d6ac7b
--- /dev/null
+++ b/src/unistd/geteuid.c
@@ -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
index 00000000..186635a2
--- /dev/null
+++ b/src/unistd/getgid.c
@@ -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
index 00000000..6f19870e
--- /dev/null
+++ b/src/unistd/getgroups.c
@@ -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
index 00000000..a406c4eb
--- /dev/null
+++ b/src/unistd/gethostname.c
@@ -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
index 00000000..06011913
--- /dev/null
+++ b/src/unistd/getlogin.c
@@ -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
index 00000000..f04f71e5
--- /dev/null
+++ b/src/unistd/getlogin_r.c
@@ -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
index 00000000..50d716b5
--- /dev/null
+++ b/src/unistd/getpgid.c
@@ -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
index 00000000..2004630a
--- /dev/null
+++ b/src/unistd/getpgrp.c
@@ -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
index 00000000..31cbe1cb
--- /dev/null
+++ b/src/unistd/getpid.c
@@ -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
index 00000000..a3241829
--- /dev/null
+++ b/src/unistd/getppid.c
@@ -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
index 00000000..064229cf
--- /dev/null
+++ b/src/unistd/getsid.c
@@ -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
index 00000000..9d4e53f5
--- /dev/null
+++ b/src/unistd/getuid.c
@@ -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
index 00000000..cff6e9fe
--- /dev/null
+++ b/src/unistd/isatty.c
@@ -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
index 00000000..30e83916
--- /dev/null
+++ b/src/unistd/lchown.c
@@ -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
index 00000000..f121bb9e
--- /dev/null
+++ b/src/unistd/link.c
@@ -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
index 00000000..0eb51221
--- /dev/null
+++ b/src/unistd/linkat.c
@@ -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
index 00000000..0dab2679
--- /dev/null
+++ b/src/unistd/lseek.c
@@ -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
index 00000000..4b28ef41
--- /dev/null
+++ b/src/unistd/nice.c
@@ -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
index 00000000..14720651
--- /dev/null
+++ b/src/unistd/pause.c
@@ -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
index 00000000..2dfc9c99
--- /dev/null
+++ b/src/unistd/pipe.c
@@ -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
index 00000000..029ba3d1
--- /dev/null
+++ b/src/unistd/pread.c
@@ -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
index 00000000..8f23d1b9
--- /dev/null
+++ b/src/unistd/pwrite.c
@@ -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
index 00000000..87ff1f10
--- /dev/null
+++ b/src/unistd/read.c
@@ -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
index 00000000..f6b1635c
--- /dev/null
+++ b/src/unistd/readlink.c
@@ -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
index 00000000..8171050d
--- /dev/null
+++ b/src/unistd/readlinkat.c
@@ -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
index 00000000..e311f9de
--- /dev/null
+++ b/src/unistd/readv.c
@@ -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
index 00000000..0dae9f11
--- /dev/null
+++ b/src/unistd/renameat.c
@@ -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
index 00000000..8e18c7a8
--- /dev/null
+++ b/src/unistd/rmdir.c
@@ -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
index 00000000..85348842
--- /dev/null
+++ b/src/unistd/setegid.c
@@ -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
index 00000000..0aaa86e0
--- /dev/null
+++ b/src/unistd/seteuid.c
@@ -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
index 00000000..00c7a03a
--- /dev/null
+++ b/src/unistd/setgid.c
@@ -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
index 00000000..748d2907
--- /dev/null
+++ b/src/unistd/setpgid.c
@@ -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
index 00000000..a2a37f65
--- /dev/null
+++ b/src/unistd/setpgrp.c
@@ -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
index 00000000..d25dab76
--- /dev/null
+++ b/src/unistd/setregid.c
@@ -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
index 00000000..0ba2277b
--- /dev/null
+++ b/src/unistd/setreuid.c
@@ -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
index 00000000..e2c5690c
--- /dev/null
+++ b/src/unistd/setsid.c
@@ -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
index 00000000..53b74d88
--- /dev/null
+++ b/src/unistd/setuid.c
@@ -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
index 00000000..d6450941
--- /dev/null
+++ b/src/unistd/sleep.c
@@ -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
index 00000000..8d380d85
--- /dev/null
+++ b/src/unistd/symlink.c
@@ -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
index 00000000..9693b226
--- /dev/null
+++ b/src/unistd/symlinkat.c
@@ -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
index 00000000..a49808fd
--- /dev/null
+++ b/src/unistd/sync.c
@@ -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
index 00000000..50080c7e
--- /dev/null
+++ b/src/unistd/tcgetpgrp.c
@@ -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
index 00000000..67c38cb4
--- /dev/null
+++ b/src/unistd/tcsetpgrp.c
@@ -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
index 00000000..f75e824e
--- /dev/null
+++ b/src/unistd/truncate.c
@@ -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
index 00000000..0f3e1141
--- /dev/null
+++ b/src/unistd/ttyname.c
@@ -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
index 00000000..f86fbd9c
--- /dev/null
+++ b/src/unistd/ttyname_r.c
@@ -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
index 00000000..be853035
--- /dev/null
+++ b/src/unistd/ualarm.c
@@ -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
index 00000000..fb577920
--- /dev/null
+++ b/src/unistd/unlink.c
@@ -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
index 00000000..47fccc17
--- /dev/null
+++ b/src/unistd/unlinkat.c
@@ -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
index 00000000..e3869017
--- /dev/null
+++ b/src/unistd/usleep.c
@@ -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
index 00000000..426cfc5b
--- /dev/null
+++ b/src/unistd/write.c
@@ -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
index 00000000..a6a118af
--- /dev/null
+++ b/src/unistd/writev.c
@@ -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
index 00000000..89f7f4d9
--- /dev/null
+++ b/tools/gen-musl-gcc.sh
@@ -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